上述代码执行功效如下
- Thread name:thread - 1 , ThreadLocal hashcode:372282300, Instance hashcode:418873098, Value:0
- Thread name:thread - 3 , ThreadLocal hashcode:372282300, Instance hashcode:1609588821, Value:0
- Thread name:thread - 2 , ThreadLocal hashcode:372282300, Instance hashcode:1780437710, Value:0
- Thread name:thread - 3 , ThreadLocal hashcode:372282300, Instance hashcode:1609588821, Value:01
- Thread name:thread - 1 , ThreadLocal hashcode:372282300, Instance hashcode:418873098, Value:01
- Thread name:thread - 3 , ThreadLocal hashcode:372282300, Instance hashcode:1609588821, Value:012
- Thread name:thread - 3 , ThreadLocal hashcode:372282300, Instance hashcode:1609588821, Value:0123
- Set, Thread name:thread - 3 , ThreadLocal hashcode:372282300, Instance hashcode:1362597339, Value:hello world
- Thread name:thread - 2 , ThreadLocal hashcode:372282300, Instance hashcode:1780437710, Value:01
- Thread name:thread - 1 , ThreadLocal hashcode:372282300, Instance hashcode:418873098, Value:012
- Thread name:thread - 2 , ThreadLocal hashcode:372282300, Instance hashcode:1780437710, Value:012
- Thread name:thread - 1 , ThreadLocal hashcode:372282300, Instance hashcode:418873098, Value:0123
- Thread name:thread - 2 , ThreadLocal hashcode:372282300, Instance hashcode:1780437710, Value:0123
- Set, Thread name:thread - 1 , ThreadLocal hashcode:372282300, Instance hashcode:482932940, Value:hello world
- Set, Thread name:thread - 2 , ThreadLocal hashcode:372282300, Instance hashcode:1691922941, Value:hello world
从上面的输出可看出
- 从第1-3行输出可见,每个线程通过 ThreadLocal 的 get() 要领拿到的是差异的 StringBuilder 实例
- 第1-3行输出表白,每个线程所会见到的是统一个 ThreadLocal 变量
- 从7、12、13行输出以及第30行代码可见,固然从代码上都是对 Counter 类的静态 counter 字段举办 get() 获得 StringBuilder 实例并追加字符串,可是这并不会将全部线程追加的字符串都放进统一个 StringBuilder 中,而是每个线程将字符串追加进各自的 StringBuidler 实例内
- 比拟第1行与第15行输出并团结第38行代码可知,行使 set(T t) 要领后,ThreadLocal 变量所指向的 StringBuilder 实例被替代
三、ThreadLocal道理
1. ThreadLocal维护线程与实例的映射
既然每个会见 ThreadLocal 变量的线程都有本身的一个“当地”实例副本。一个也许的方案是 ThreadLocal 维护一个 Map,键是 Thread,值是它在该 Thread 内的实例。线程通过该 ThreadLocal 的 get() 方案获取实例时,只必要以线程为键,从 Map 中找出对应的实例即可。该方案如下图所示

该方案可满意上文提到的每个线程内一个独立备份的要求。每个新线程会见该 ThreadLocal 时,必要向 Map 中添加一个映射,而每个线程竣事时,应该破除该映射。这里就有两个题目:
- 增进线程与镌汰线程均必要写 Map,故需担保该 Map 线程安详。固然从ConcurrentHashMap的演进看Java多线程焦点技能一文先容了几种实现线程安详 Map 的方法,但它或多或少都必要锁来担保线程的安详性
- 线程竣事时,必要担保它所会见的全部 ThreadLocal 中对应的映射均删除,不然也许会引起内存走漏。(后文会先容停止内存走漏的要领)
个中锁的题目,是 JDK 未回收该方案的一个缘故起因。
2. Thread维护ThreadLocal与实例的映射 (编辑:湖南网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|