Java基础(1)——ThreadLocal

本文详细介绍了Java中的ThreadLocal类,包括get、set、remove方法的工作原理,重点解析了ThreadLocalMap的实现及内存泄露问题,强调了在使用ThreadLocal时及时调用remove方法的重要性。
摘要由CSDN通过智能技术生成

1. Java基础(1)——ThreadLocal

1.1. ThreadLocal

ThreadLocal是一个泛型类,当我们在一个类中声明一个字段: private ThreadLocal<Foo> threadLocalFoo = new ThreadLocal<>(); 时,这时候,即使不同的线程持有了该类的同一个实例,那么它们在访问该实例的 threadLocalFoo 的时候访问的是不同的Foo对象,这些Foo对象和这些线程是一一对应的关系,并被这些线程所私有,因此每个线程不需要对自己从 threadLocalFoo 获得的Foo实例进行加锁(加锁也没用啊),这种无锁化的设计提高了并行能力,但注意ThreadLocal并不是万能的,有些场景可以使用ThreadLocal(比如Spring中的事务),但有些场景它的语义就是必须对同一个对象实例进行加锁后独占地访问,比如单例模式,这种ThreadLocal就起不了作用了。

当然ThreadLocal还提供了 initialValue 这个protected方法,用来创建声明的泛型类型对象,因此我们还可以以下面这种方式来声明一个thread local:

ThreadLocal<Foo> threadLocal = new ThreadLocal<Foo>(){

            @Override
            protected Foo initialValue() {
                return new Foo();
            }
        };

同时ThreadLocal还提供了一个 withInitial 静态方法,该方法接收一个相同泛型类型的Supplier,返回ThreadLocal。

Java的每个Thread实例中,都有一个ThreadLocalMap类型的实例字段,它存放了该线程所用到过的所有 ThreadLocal 式样的实例对象,比如,有个类中声明了这个字段 private ThreadLocal<Foo> threadLocalFoo = new ThreadLocal<>(); ,虽然它的一个实例被多个线程持有,但这些线程不一定都访问过这个实例的 threadLocalFoo 字段,只有访问过这个字段的Thread,它的thread local map中才会存Foo对象(以Entry的方式存,key为该ThreadLocal实例(共享),value为每个线程自己持有的Foo对象(私有))。

注意,我们使用ThreadLocal的是因为有些对象每个线程都可以持有一份,然后我们才使用ThreadLocal来避免同一个对象的实例方法的并发操作,但这样的话我们要谨防ThreadLocal的退化:如果使用它的时候,用之前都是set,之后就remove,那么相当于每访问一次ThreadLocal都要创建出一个新的对象出来,这样发挥不出ThreadLocal节省对象数量的作用。ThreadLocal一般被声明为static字段。

1.1.1. get方法

如果当前的Thread中的thread local map字段不空,并且其中存的有对应的对象,那么返回。

如果thread local map字段不空,但是没有存对应的对象,那么使用initialValue创建对象,然后将它和该ThreadLocal实例,打包成Entry放入当前的thread local map中,返回创建的对象。

如果thread local map字段为空,那么首先创建对象,然后创建该线程的thread local map,然后再存Entry,再返回创建的对象。

总而言之呢,get方法就是说返回的对象都必须从当前线程的thread local map中取,thread local map没创建,就创建thread local map,创建了但里面没有需要的对象,那么就创建对象并将其塞进去,反正必须从thread local map中拿就对了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值