ThreadLocal是什么?有啥用?怎么用?????????
一、ThreadLocal理解
1、ThreadLocal又名线程局部变量,是Java中一种较为特殊的线程绑定机制,可以为每一个使用该变量的线程都提供一个变量值的副本,并且每一个线程都可以独立地改变自己的副本,而不会与其他线程的副本发生冲突。
2、如果某个变量要被某个线程独享,那么我们就可以通过ThreadLocal来实现本地存储功能。
3、每个线程都有关于该ThreadLocal变量的私有值,并且对其他线程是不可见的。
二、应用场景
1、类ThreadLocal主要解决的就是为每个线程绑定自己的值,以方便其处理自己的状态;
形象的讲,可以将ThreadLocal变量比喻成全局存放数据的容器,容器中可以存储每个线程的私有数据
2、demo
运行结果:
运行结果:
可以看出,ThreadLocal可以给一个初始值,而每个线程都会获得这个初始化值的一个副本。
三、ThreadLocal的接口方法
1、void set(Object value)设置当前线程的线程局部变量的值。
2、public Object get()该方法返回当前线程所对应的线程局部变量。
3、public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK5.0新增的方法。需要指出的是,当线程结束后,对应线程的局部变量将自动被垃圾回收,所以显示调用该方法清除的局部变量并不是必须的操作,但它可以加快内存回收的速度。
4、protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null.
在JDK5.0中ThreadLocal已经支持泛型,该类的类名已经变为ThreadLocal。API方法也相应进行了调整,新版本的API方法分别是void set(T value)、T get()以及T initialValue()。
ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。
四、有什么用?
ThreadLocal是解决线程安全问题一个很好的额思路,它通过为每个线程提供一个独立副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序用于更高的并发性。
五、底层原理
六、总结
在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量ThreadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()或set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到ThreadLocals,然后在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLcoals里面查找。
1、实际得通过ThreadLocal创建的副本是存储在每个线程自己的ThreadLocal中的
2、为何ThreadLocal的类型ThreadLocalMap的键值为ThreadLocal的对象,因为每个线程中可有多个ThreadLocal变量
3.在进行get之前,必须先set,否则会报空指针异常,如果想在get之前不需要调用set就能正常访问的话,必须重写initialValue()方法。因此在上面的代码分析过程中,我们发现如果没有先set的话,即在map中查找不到对应的存储,则会通过调用setInitialValue方法返回i,而在setInitialValue方法中,有一个语句是T value = initialValue(),而默认情况下,initialValue方法返回的是null。