threadlocal是同一个线程内共享数据的工具。
为什么threadlocal可以实现线程内的数据共享?- 首先来看看thread类,thread类中有一个对象叫 threadlocals,是 threadlocal的内部类 threadlocalmap
- 那我们来看看threadlocalmap是什么。可以看到threadlocalmap就是一个map,只不过key是 弱引用 value是强引用
- 所以可以推断出,thread类中有一个map,这个map的key是threadlocal对象,value就是自定义的值。所以相当于一个全局变量,在一个线程中设置可以在另一个地方取出来,只要用同一个 threadlocal即可
我们接下来看看 Thread类是如何和threadlocal产生关联的
- 我们来看看threadlocal的set方法。 拿到当前线程,获取这个线程的map,把自己和value插入到这个map中
- get方法。 拿到当前线程,自己就是key获取value
首先来分析为什么threadlocal的key要定义为弱引用。如果定义为强引用,则创建了threalocal调用了set方法之后,当前thread里面的map就会有一个强引用指向threadlocal,即使我们创建的threadlocal引用失效之后,线程的指针还是强引用。只有当前线程消失才会释放。
所以需要设置为弱引用,当创建threadlocal的失去引用之后,thread里面的map引用就会在下一次GC被回收。
如果不调用 remove方法的后果
如果不调用remove方法,直接把threadlocal置空,thread里面的key会在下一次GC的时候被回收,但是value就会保存在thread里面。存在内存泄漏问题。但是threadlocal在每次的set 和get的时候会判断当前map里面的哪些key是空的,如果有空的就把value释放。
因为thread中的那个threadlocalmap 的key是弱引用,弱引用是第一次GC就会被回收的东西
静态变量引用threadlocal
大部分实际情况threadlocal都作为一个静态变量来使用,这里会导致的问题就是在web容器中都是线程池,如果没有及时的remove掉。假设有100个线程在池子里,在高并发的时候这100个线程都被拿来工作,里面放入了数据。然后没有调用remove方法,当闲下来的时候,只有10个线程在处理逻辑,然后这10个线程里面的threadlocal的value会被替换,剩下的90个线程里面的数据就泄漏了。
使用 InheritableThreadLocal 可以在子线程直接传递数据
thread类中除了有 threadlocalmap还有一个对象 inheritableThreadLocals 用来存储从父类继承下来的数据
InheritableThreadLocal 的获取和创建map的动作都是把数据放到了 Thread 的 inheritableThreadLocals 对象中
我们再来看 创建线程的时候做了什么事情
所以使用 inheritableThreadLocals 可以实现父子线程的共享
自定义线程池实现



