AI智能
改变未来

《Java高并发程序设计》 –ThreadLocal

public class ThreadLocalDemo {static ThreadLocal<Integer> local = new ThreadLocal<Integer>(){@Overrideprotected Integer initialValue() {return 0;}};public static void main(String[] args) {Thread[] threads = new Thread[5];for (int i = 0; i < 5; i++) {threads[i] = new Thread(()->{Integer num = local.get();local.set(num+ 5);System.out.println(Thread.currentThread().getName()+ \"-\" + num);});}for (int i = 0; i < 5; i++) {threads[i].start();}}}

代码输出:

Thread-0-0Thread-3-0Thread-4-0Thread-2-0Thread-1-0

解释:

各个线程获取的值不会受到其他线程修改值的影响

原理大致如图:

对流程的说明:

对于新开启的一个线程Thread,内部有一个ThreadLocalMap对象(类似于hash map)存储供当前线程使用的自定义的Object value。

该map的key为ThreadLocal实例,值为用户自定义使用的值。

下面就解析一下ThreadLocal的set方法

这个方法分为两步走:

  1. 创建新的ThreadLocalMap
  2. 将当前的ThreadLocal放入到已有的ThreadLocalMap中

看第一步:

ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {table = new Entry[INITIAL_CAPACITY];int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);table[i] = new Entry(firstKey, firstValue);size = 1;setThreshold(INITIAL_CAPACITY);}

就是ThreadLocalMap的构造函数啦, 给table赋值一个 初始化大小的Entry数组,再根据threadLocal的hashcode和长度进行&比较获取table中的下标,然后插入新的Entry值。

看第二步啦:

这有三个if,一个for:

for: 遍历ThreadLocalMap中的Entry数组,找到不为空的进行判断

  1. 如果是同一个坑的key,直接覆盖value
  2. 如果k为空,也就是threadLocal为空但是value还存在的情况,

注释:当一个ThreadLocal失去强引用,生命周期只能存活到下次gc前,此时ThreadLocalMap中就会出现key为null的Entry,当前线程无法结束,这些key为null的Entry的value就会一直存在一条强引用链,造成内存泄露。

for 循环遍历结束后,将在对应的table位置新建一个entry存放新值。

并处理那些标记为需要清除的slot entry ,并进行rehash

  

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 《Java高并发程序设计》 –ThreadLocal