В потоках есть метод, который все часто вызывают, — ThreadLocal. Однако ThreadLocal также столкнется с более сложными проблемами при обработке памяти, и всегда будут возникать некоторые утечки памяти. В этой статье будет использоваться пример утечки для анализа для всех, а также поможет вам понять некоторые ситуации с утечкой и предложить соответствующие решения ThreadLocal.
1. Примеры утечек
Статический внутренний класс. Запись ThreadLocalMap:
статический класс Entry расширяет WeakReference<ThreadLocal<?>> { /** Значение, связанное с этим ThreadLocal */. Стоимость объекта; Entry(ThreadLocal<?> k, Object v) { супер(к); значение = v; } }
ThreadLocalMap использует статический внутренний класс Entry для реализации хранилища <k, v>, а Entry наследует класс WeakReference, поэтому ключ в ThreadLocalMap на самом деле является слабой ссылкой на ThreadLocal.
Именно потому, что ThreadLocalMap использует слабую ссылку ThreadLocal в качестве ключа, когда этот ThreadLocal не имеет внешней сильной ссылки, это будет GC. В это время в ThreadLocalMap появится запись с нулевым ключом. Конечно, значение этой записи никогда не будет доступно.
В этом случае, если текущий рабочий поток не завершился, то на значение с нулевым ключом строго ссылается Entry, а на Entry строго ссылается ThreadLocalMap текущего потока, в результате чего это значение никогда не будет GCed, вызывая память. утечка.
2. Решение
Методы cleanSomeSlots() и expungeStaleEntry() ThreadLocalMap могут очищать значения с помощью нулевых ключей. В методах set(), get() и Remove() класса ThreadLocal будут вызываться cleanSomeSlots() или expungeStaleEntry() для очистки всех значений с нулевыми ключами в ThreadLocalMap.
Вышеописанное — решение проблемы утечки памяти Java ThreadLocal. Конечно, это может сыграть лишь определённую роль в утечках памяти. Ведь это всего лишь некая ясность и нет никакой гарантии, что этого не произойдет .