ThreadLocal是什么?
ThreadLocal是java提供的存储线程局部变量的对象。在多线程下除了使用锁同步避免并发问题,也可以考虑以空间换时间,使用ThreadLocal。
优点&缺点
优点:ThreadLocal存储的对象被当前线程独享,可以避免多线程资源竞争问题。 缺点:ThreadLocal使用不当可能引起内存泄漏(具体原因见下文),所以使用时需要注意在finally中调用remove清掉对象。
ThreadLocal对象引用关系
ThreadLocal<Object> th = new ThreadLocal<Object>();
Object o = new new Object();
th.put(o);
ThreadLoaclMap 中对ThreadLocal对象是弱引用,但是value中Object o是强引用,如果使用完成后未remove并且线程Thread一直存活,o对象引用会一直存在,可能引起内存泄漏。
ThreadLocal的实现中,无论是get()、set()在某些时候,调用了expungeStaleEntry方法用来清除Entry中Key为null的Value,但是这是不及时的(如果不再调用set/get方法呢?), 只有 remove()方法中显式调用了expungeStaleEntry 方法。
ThreadLocal使用场景
常见的场景如log4j2 中日志唯一流水 MDC机制,Spring 事务传播机制等等。 需要注意的是线程池中使用ThreadLocal,由于线程可能复用,使用完ThreadLocal一定要remove,不然可能取到上次遗留的值。