ThreadLocal是用来存储每一个线程的数据的,使用set和get来读写数据。
ThreadLocal<Object> local = new ThreadLocal<>();
local.set(6);
System.out.println(local.get());
ThreadLocal是用来维护ThreadLocalMap的。set和get操作都是对ThreadLocalMap操作。
每一个Thread都有一个单独的ThreadLocalMap。
ThreadLocalMap定义是在Thread里面,使用是在threadlocal里面。
ThreadLocalMap其实是一个默认大小16的数组,一个线程的每一个ThreadLocal占用一个位置,这是通过ThreadLocalMap里面的threadLocalHashCode对数组长度取模实现的。
ThreadLocal内存溢出
存储数据的Entry的key的ThreadLocal采用的弱引用,能被清理掉,但是value是强引用,引用关系为:Thread -> ThreadLocalMap -> Entry -> Value,只要该线程不死,那么这个强引用就一直存在,不会被清理掉,导致内存溢出。
解决方法为:
虽然ThreadLocal的作者想到了这点,也做了些优化,例如在get的时候当发现key是null的时候,会遍历一次整个Entry数组,remove掉key为null的entry,把value指向null,消除这条强引用链。源码方法为expungeStaleEntry。
所以开发者要养成良好的习惯,记得用完ThreadLocal时,调一次ThreadLocal.remove()方法或者ThreadLocal.set(null)