ThreadLocal学习笔记

时间:2021-07-24 02:44:34

首先,ThreadLocal是Java语言提供的用于支持线程局部变量的标准实现类。很多时候,ThreadLocal与Synchronized在功能上有一定的共性,都可以用来解决多线程环境下线程安全问题。但是它们之间区别很大:Synchronized是通过同步的方式来管理多个线程对共享对象状态的访问以保证应用程序的线程安全;ThreadLocal是通过消除对象的共享以保证应用程序的线程安全。所以,共享对象是ThreadLocal尽量避免的,如果管理的对象非要共享,ThreadLocal就处理不了。
虽然是通过ThreadLocal来设置特定于各个线程的数据资源,但ThreadLocal自身不会保存这些数据资源。前面说过,数据资源是特定于线程的,自然是由每个线程自己来保存和管理。具体的实现原理是:每个Thread类都有一个ThreadLocal.ThreadLocalMap类型的名为threadLocals的实例变量,它就是保持那些通过ThreadLocal设置给这个线程的数据资源的地方。当通过ThreadLocal的set(data)方法来设置数据的时候,ThreadLocal会首先获取当前线程的引用,然后通过该引用获取当前线程持有的threadLocals,最后,以当前ThreadLocal作为Key,将要设置的数据设置到当前线程,如下所示:
Thread thread = Thread.currentThread();
ThreadLocalMap threadLocalMap = thread.threadLocals;
...
threadLocalMap.set(this, data);
至于ThreadLocal中的get()等方法,程序逻辑也是类似的,都是首先取得当前线程,然后根据每个方法的语义,但当前线程所持有的threadLocals中的数据进行操作。实际上,我们可以把ThreadLocal看作是一个窗口,通过这个窗口,我们可以将特定于线程的数据资源绑定到当前线程,也可以通过这个窗口获取绑定的数据资源,当然,更可以解除之前绑定到当前线程的数据资源。在整个线程的生命周期内,我们都可以通过ThreadLocal这个窗口与当前线程打交道。
      基本上,我们可以从两个方面来看待并灵活应用ThreadLocal。
ThreadLocal横跨多个线程的能力,直接为每个线程分配一份自己特定的数据资源。
ThreadLocal在单一线程内可以发挥作用,通过ThreadLocal设置的特定于各个线程的数据资源,可以随着所在线程的执行"随波逐流"。
这两个特性是相互依存,紧密结合的。在充分发挥ThreadLocal两方面的基础上,我们可以发掘出以下几种ThreadLocal的应用场景。
管理应用程序实现中的线程安全。
实现当前程序执行流程内的数据传递。
某些情况下的性能优化。
per-thread Singleton。