ThreadLocal使用总结

ThreadLocal介绍:

ThreadLocal是Thread的一个局部变量,主要用于一个线程在业务流程相对复杂的情况下,进行数据的存储和使用,比如:用户的登录信息,锁的信息等。

ThreadLocal使用:

在定义ThreadLocal时要将其设置为静态变量(原因后面解释)

static ThreadLocal<String> lockThreadLocal = new ThreadLocal<>();
复制代码

使用时利用set和get进行设置、获取值

⚠️注意:ThreadLocal存储的对象不需要使用线程安全类型,因为ThreadLocal本身是线程安全的

ThreadLocal原理:

每个Thread中都有一个ThreadLocal.ThreadLocalMap对象。在ThreadLocalMap中,也是初始化一个大小16的Entry数组,Entry对象用来保存每一个key-value键值对,key为弱引用指向的ThreadLocal对象,value为ThreadLocal set的值。

如下图:

由于ThreadLocalMap的key是WeakReference指向的,如果没有外部强引用指向,在下一次发生gc的时候就会被回收,当ThreadLocal在进行set或get操作时会清理key为null的entry,这样虽然可以一定程度上防止内存泄漏,但是如果在ThreadLocal后没有进行get和set操作,entry中的value就不会回收,而在tomcat容器中,使用的是线程池,当前线程使用完后不会进行回收,进入线程池等待下次调用,这样就会导致内存泄漏,所以在使用完后要进行remove操作。

关于ThreadLocal对象是否设置为static的利弊:

static:

优点 减少了ThreadLocal对象的创建,并且降低了因重复创建ThreadLocal导致的数据错乱

缺点 ThreadLocal.ThreadLocalMap的弱引用无法生效,如果ThreadLocal忘记remove,则会造成key一直存在,value无法回收(虽然ThreadLocal被gc变成null,也不能确保一定不会发生内存泄漏)

非static:

优点 由于ThreadLocal.ThreadLocalMap的key是弱引用,在线程执行完后,会断开ThreadLocal的链路,这样ThreadLocal不可达就会被gc

缺点 对象多,而且因为ThreadLocal多容易造成取数错误,因为ThreadLocal是key(容易导致bug)

结论:建议ThreadLocal设置为static对象,在使用完后进行remove操作,既避免了内存泄漏也避免了由于key使用不当导致的bug。

猜你喜欢

转载自juejin.im/post/5e859bf5f265da47b554e1b2