随笔 - 72  文章 - 0  评论 - 0  阅读 - 5401

ThreadLocal

介绍

线程本地变量,访问这个变量的每个线程都会有这个变量的一个本地拷贝,多个线程操作这个变量的时候,实际是在操作自己本地内存里面的变量,从而起到线程隔离的作用,避免了并发场景下的线程安全问题

 

 

复制代码
public class ThreadLocalUse {
    private static final ThreadLocal<DateFormat> DATE_FORMAT_THREAD_LOCAL = new ThreadLocal<DateFormat>(){
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };
    public static Date convert(String source) throws ParseException {
        return DATE_FORMAT_THREAD_LOCAL.get().parse(source);
    }
    /**
     * @description Removes the current thread's value for this thread-local variable.
     */
    public static void remove(){
        DATE_FORMAT_THREAD_LOCAL.remove();
    }
}
复制代码

 

应用场景

日期工具类DateUtil中会用ThreadLocal来让每个线程装在自己的SimpleDateFormat对象

 

spring提供了事务相关的操作,一次事务的所有操作需要在同一个数据库连接上,但是不需要我们关注

spring就是用 ThreadLocal来实现的,ThreadLocal存储的类型是一个Map

Map中的key是DataSource,value是Connection(为了应对多数据源的情况,所以是一个Map)

用了ThreadLocal保证了同一个线程获取一个Connection对象,从而保证一次事务的所有操作需要在同一个数据库连接上

 

 

ThreadLocal原理

threadLocal真正存储数据的是内部类ThreadLocalMap,ThreadLocalMap的引用是在Thread上定义的

 

 

Thread类里面有两个变量 ,htreadLocals和inheritableThreadLocals,都是ThreadLocal.ThreadLocalMap类型的变量,当前线程调用ThreadLocal的set、get方法时创建

ThreadLocalMap的key是ThreadLocal,value是set的值,线程内创建多个ThreadLocal共用线程仅有的ThreadLocaLMap

 

 为什么不是Thread作为key?

一个线程可以拥有多个私有变量,key是当前线程的话,还需要用唯一标识来标识set进去的value

并发量大时,所有线程去操作同一个Map,Map体积可能会膨胀,导致访问的性能下降

该Map维护着所有线程的私有变量,意味着不知道什么时候可以销毁

threadLocal作为key,线程销毁了,ThreadLocal也会被销毁

 

ThreadLocal内存泄露

ThreadLocalMap 中使⽤的 key 为 ThreadLocal 的弱引⽤,⽽ value 是强引⽤。所以,如果ThreadLocal 没有被外部强引⽤的情况下,在垃圾

回收的时候,key 会被清理掉,⽽ value 不会被清理掉。这样⼀来, ThreadLocalMap 中就会出现 key 为 null 的 Entry。假如我们不做任何

措施的话,value 永远⽆法被 GC 回收,这个时候就可能会产⽣内存泄露

ThreadLocalMap实现中已经考虑了这种情况,在调用set()、get(),remove方法的时候,会清理掉key为null的记录。使用完ThreadLocal方法

后,最好手动remove()一下。

 

概率非常低 ThreadLocal会被两种引用指向

1):ThreadLocalRef->ThreadLocal(强引⽤,被对应的栈引用关联,创建Thread时,栈引用-》Thread-》Thread内部维护了ThreadLocalMap的引用)

2):ThreadLocalMap Entry key ->ThreadLocal(弱引⽤)

只要ThreadLocal没有被回收,那ThreadLocalMap key的指向就不会再GC时 被断开,也就不会有内存泄露

 

posted on   or追梦者  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示