Почему java.lang.ThreadLocal является картой в Thread, а не в ThreadLocal? - PullRequest
1 голос
/ 02 декабря 2009

Наивно, я ожидал, что ThreadLocal будет чем-то вроде WeakHashMap of Thread для типа значения. Поэтому я был немного озадачен, когда узнал, что значения ThreadLocal на самом деле сохраняются на карте в Thread . Почему это было сделано таким образом? Я ожидаю, что утечки ресурсов , связанной с ThreadLocal, не будет, если значения будут сохранены в самом ThreadLocal.

Разъяснение: я думал о чем-то вроде

public class AlternativeThreadLocal<T> { 
    private final Map<Thread, T> values = 
        Collections.synchronizedMap(new WeakHashMap<Thread, T>());
    public void set(T value) { values.put(Thread.currentThread(), value); }
    public T get() { return values.get(Thread.currentThread());}    
}

Насколько я вижу, это предотвратило бы странную проблему, заключающуюся в том, что ни ThreadLocal, ни его оставшиеся значения никогда не будут собираться мусором до тех пор, пока Thread не умрет, если значение каким-либо образом строго ссылается на сам ThreadLocal. (Вероятно, наиболее хитрая форма этого происходит, когда ThreadLocal является статической переменной в классе, на который ссылается значение. Теперь у вас есть большая утечка ресурсов при повторном развертывании на серверах приложений, поскольку ни объекты, ни их классы не могут быть собраны.)

Ответы [ 4 ]

8 голосов
/ 02 декабря 2009

Иногда вы становитесь просветленными, просто задавая вопрос. :-) Теперь я только что увидел один из возможных ответов: безопасность потоков. Если карта со значениями находится в объекте Thread, вставка нового значения является тривиально поточно-ориентированной. Если карта находится в ThreadLocal, у вас есть обычные проблемы параллелизма, которые могут замедлить процесс. (Конечно, вы бы использовали ReadWriteLock вместо синхронизации, но проблема остается.)

4 голосов
/ 02 декабря 2009

Вы, кажется, неправильно понимаете проблему утечек ThreadLocal. Утечка ThreadLocal происходит, когда один и тот же поток используется повторно, например, в пуле потоков, и состояние ThreadLocal не очищается между использованиями. Они не являются следствием того, что ThreadLocal остается, когда поток уничтожается, поскольку ничто не ссылается на карту ThreadLocal, кроме самого потока.

Наличие слабо ссылающейся карты Thread на локальные объекты потока не предотвратит проблему утечки ThreadLocal, поскольку поток все еще существует в пуле потоков, поэтому локальные объекты потока не могут быть собраны, когда поток повторно используется из бассейн. Вам все равно придется вручную очищать ThreadLocal, чтобы избежать утечки.

Как вы сказали в своем ответе, управление параллелизмом упрощается, так как Карта ThreadLocal является отдельным экземпляром на поток. Это также делает невозможным доступ одного потока к локальным объектам другого потока, что может быть не так, если объект ThreadLocal предоставил API на предложенной вами карте.

0 голосов
/ 02 декабря 2009

Почему Map будет на ThreadLocal? Это не имеет большого смысла. То есть это будет карта ThreadLocal с объектами внутри ThreadLocal?

Простая причина, по которой это Карта Thread s для Объектов, заключается в том, что:

  1. Это деталь реализации, т.е. Map никак не раскрывается;
  2. Всегда легко определить текущий поток (с помощью Thread.currentThread()).

Также идея заключается в том, что ThreadLocal может хранить разные значения для каждого потока, который его использует, поэтому имеет смысл, что он основан на Thread, не так ли?

0 голосов
/ 02 декабря 2009

Я помню, как несколько лет назад Sun изменила реализацию локальных потоков на свою текущую форму. Я не помню, какая это была версия и какой был старый impl.

В любом случае, для переменной, для которой у каждого потока должен быть слот, Thread является естественным контейнером выбора. Если бы мы могли, мы бы также добавили нашу локальную переменную потока непосредственно как член класса Thread.

...