英文:
When the Object referenced by ThreadLocal.ThreadLocalMap.Entry's key is collected by the GC collector
问题
ThreadLocal通常被用作类的静态字段,就像这样:
public static ThreadLocal<String> userSessionName = new ThreadLocal();
也就是说,userSessionName是一个GC根,即使线程已经结束,它也不会被回收,直到类被卸载。那么,在调用get方法后,ThreadLocalMap中的条目什么时候会返回null?换句话说,ThreadLocalMap中的条目键什么时候会变成null?
英文:
ThreadLocal is often used as a class static filed like
public static ThreadLocal<String> userSessionName = new ThreadLocal();
That is to say, userSessionName is a GC root,and it would never be collected until the class is unloaded even if the thread id dead. So, when will the Entry in ThreadLocalMap return null after calling get method,in other words,when will the ThreadLocalMap.Entry's key be null ?
答案1
得分: 2
一个线程的ThreadLocalMap
会在线程存活期间保持可访问。当线程退出时,对映射的引用会被断开;也就是在Thread
变得不可访问之前。
只要映射可访问,映射中的条目就是可访问的。可以通过调用ThreadLocal.remove
来显式地从映射中移除条目……但这不会自动发生。
(实际上,这并不完全正确。继续阅读。)
在Java 11版本的代码中,以下注释部分部分地解答了您的后续问题:
> ThreadLocalMap
是一个定制的哈希映射,仅适用于维护线程本地值。在ThreadLocal
类之外不会导出任何操作。该类对包外部是私有的,允许在Thread
类中声明字段。为了处理非常大且生命周期长的用法,哈希表条目使用WeakReferences
作为键。然而,由于没有使用引用队列,只有在表开始耗尽空间时,才保证会移除陈旧的条目。
这里所指的键是WeakReference<ThreadLocal<?>>
。
如果应用程序对其ThreadLocal
对象有强(普通)引用,任何现存线程的任何映射中的相应值都将被保留。如果应用程序失去对ThreadLocal
的(强)引用,那么相应的值可能会被移除。这只会在以下情况下发生:
- 有足够的内存压力导致
WeakReference
断开,且 - 特定的
ThreadLocalMap
正在得到大量活动。
(“耗尽空间”注释与代码的实际操作并不完全一致。它似乎比这更积极。查看代码并自行判断。请注意,这是实现相关的行为。)
但无论如何,如果应用程序仍然对ThreadLocal
对象有强引用,映射中的相应值不会被设置为null……除非应用程序明确这样做。
英文:
A thread's ThreadLocalMap
remains reachable as long as the thread is alive. The reference to the map is broken when the thread exits; i.e. before the Thread
becomes unreachable.
Entries in the map are reachable as long as the map is reachable. Entries can be removed from the map explicitly by calling ThreadLocal.remove
... but this doesn't happen automatically.
(Actually, this is not entirely correct. Read on.)
The following comments in the Java 11 version of the code partially address your followup question:
> ThreadLocalMap
is a customized hash map suitable only for maintaining thread local values. No operations are exported outside of the ThreadLocal
class. The class is package private to allow declaration of fields in class Thread
. To help deal with very large and long-lived usages, the hash table entries use WeakReferences
for keys. However, since reference queues are not used, stale entries are guaranteed to be removed only when the table starts running out of space.
The keys that this is referring to are WeakReference<ThreadLocal<?>>
.
If the application has a strong (i.e. ordinary) reference to its ThreadLocal
object, any corresponding values in any map for any extant thread will be kept. If the application loses its (strong) reference to the ThreadLocal
, then corresponding values may be removed. This will only occur when:
- there is sufficient memory pressure to cause the
WeakReference
to break, AND - the specific
ThreadLocalMap
is getting a lot of activity.
(The "running out of space" comment don't entirely line up with what the code does. It seems to be a bit more aggressive than that. Look at the code and make up your own mind. Noting that this is implementation dependent behavior.)
But either way, if the application still has a strongly reachable reference to a ThreadLocal
object, corresponding values in maps won't be nulled ... unless the application does it explicitly.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论