本文已参与「新人创作礼」活动,一起开启掘金创作之路。
ThreadLocal的设计理念与作用
- 原理:ThreadLocal 是一个线程的内部存储类(也叫线程本地变量\线程本地存储),可以在每个线程的内部存储数据,当某个数据的作用域应该对应线程的时候就应该使用它; 每个线程中都会维护一个ThreadLocal.ThreadLocalMap类型的成员变量 threadLocals,当在某个线程中访问时,会取出这个线程自己的Map并且用当前ThreadLocal对象做Key值来取出相对应的Value值,从而达到不同线程不同值的效果。
- 执行流程:
- 初始化时,在 Thread 里面的 threadLocals 为空,当通过 ThreadLocal 变量调用 get() 或 set() 方法,就会对 Thread 类中的 threadLocals 进行初始化,并且以当前 ThreadLocal 变量为Key值,以 ThreadLocal 要保存的副本变量为Value,存到 threadLocals。
- 然后在当前线程里,若要使用副本变量,可以通过 get() 方法在 threadLocals 里查找。
- 最常见的 ThreadLocal 使用场景:数据库连接,Session管理等。
- ThreadLocal 的部分方法:
// 用来获取ThreadLocal在当前线程中保存的变量副本 public T get() { } // set()用来设置当前线程中变量的副本 public void set(T value) { } // remove()用来移除当前线程中变量的副本 public void remove() { } // initialValue()是一个protected方法,一般是用来在使用时进行重写的 protected T initialValue() { }
InheritableThreadLocal的设计理念与使用
- 原理:如果子线程想要拿到父线程的中的 ThreadLocal 值怎么办呢?比如会有以下的这种代码的实现。由于 ThreadLocal 的实现机制,在子线程中 get 时,我们拿到的 Thread 对象是当前子线程对象,那么他的 ThreadLocalMap 是 null 的,所以我们得到的 value 也是 null。InheritableThreadLocal 可以解决父子线程间 ThreadLocal 传递的问题。
final ThreadLocal threadLocal=new ThreadLocal(){ @Override protected Object initialValue() { return "xiezhaodong"; } }; new Thread(new Runnable() { @Override public void run() { threadLocal.get();//NULL } }).start(); - 执行流程:
- 在创建 InheritableThreadLocal 对象的时候赋值给线程的 ==t.inheritableThreadLocals 变量==。
- 在创建新线程时会 check 父线程中 t.inheritableThreadLocals 变量是否为null,如果不为null则copy一份 ThradLocalMap 到子线程的 t.inheritableThreadLocals 成员变量中去。
- 因为复写了 getMap(Thread) 和 CreateMap() 方法,所以 get 值的时候,就可以在 getMap(t) 的时候就会从 t.inheritableThreadLocals 中拿到 map 对象,从而实现了可以拿到父线程 ThreadLocal 中的值。
- InheritableThreadLocal 的部分方法(继承自ThreadLocal,并且重写了父类的方法):
protected T childValue(T var1) { return var1; } ThreadLocalMap getMap(Thread var1) { return var1.inheritableThreadLocals; } void createMap(Thread var1, T var2) { var1.inheritableThreadLocals = new ThreadLocalMap(this, var2); }
TransmittableThreadLocal设计理念及使用
- 前提:实际使用线程时并非简单的 new Thread 对象,而是使用线程池。
- 线程池特点:
- 减少创建线程的开销,线程池会缓存已经使用过的线程。
- 生命周期统一管理,合理的分配系统资源。
- 线程池特点:
- 原理:TransmittableThreadLocal 是Alibaba开源的、用于解决 “在使用线程池等会缓存线程的组件情况下传递 ThreadLocal” 问题的 InheritableThreadLocal 扩展。 如果要 TransmittableThreadLocal 在线程与主线程间传递,要配合 TtlRunnable 和 TtlCallable 使用。
- TransmittableThreadLocal 的部分方法(继承自InheritableThreadLocal):