为什么ThreadLocal可以使用static
对于ThreadLocal而言,在ThreadLocal类中有一个ThreadLocalMap类,这是一个map类,key值为ThreadLocal,value为object,key值的引用类型为弱引用,object为强引用。
static是java的一个类型申明,若申明的是实体,那么该实体就会变成静态实体,
public static ThreadLocal threadLocal = new ThreadLocal();
如果向以上这么声明,那么该threadLocal会变成静态对象,成为gc root 对象。那么在使用过程中是不是会出现以下的情景:
首先一个线程在使用了这个threadLocal存储一个String对象(我在这用一个String为例子,但是String不太适合这个场景,可能User这种类更加适合)。在这个线程结束运行后,该线程对threadLocal的引用已经结束,但是static的引用还是可达的,毕竟他是root对象。那么对于ThreadLocalMap而言,这个弱引用将被持续持有。对于Map中的value释放,需要在get,set。。等方法时查看threadLocal是否过期,来决定是否放弃对value的引用。若threadLocal持续的被持有,那么Map中的Object也将不能被释放。从而导致一个内存泄漏的问题。
既然static会导致这么一个问题,那为什么还需要使用呢。
其实是场景中的某一个环节出现了问题:
为解释threadLocal可以使用static最重要的是解释,是因为在map中的这个ThreadLocal并不是static的这个threadLocal;还是因为map在每个线程是不同的。对于阿里规范中的解释说明:为了避免重复创建TSO。既然map 不是线程独有的,那么谁是被创建的那个TSO呢?
//java.lang.Thread class包含一个实例变量,如图所示。
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocalMap是在线程中相互隔离的,这一点确保了不同线程之间不会相互访问,我们可以看到ThreadLocal中的源码,可以发现,map并不是静态的,所以在每个线程中将会拥有它自己的threadLocals映射副本。