本文分为两部分,上部分为使用方式,下部分为解析
1.使用ThreadLocal
// 大家都知道在Tl(ThreadLocal)中 数据可以在Thread中共享
// 那么以下场景会存在问题
ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
threadLocal.set(1);
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(threadLocal.get()); //输出null 因为开启了新的线程
}
}).start();
2.使用InheritableThreadLocal
// 这时使用InheritableThreadLocal (ThreadLocal的子类) 可以解决上述问题
ThreadLocal<Integer> InheritableThreadLocal = new InheritableThreadLocal<>();
InheritableThreadLocal.set(1);
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(InheritableThreadLocal.get()); //输出1
}
}).start();
3.InheritableThreadLocal在线程池场景中存在的问题
// 但是我们实际使用中,不可能每次使用都new Thread,一般都是使用线程池,这时就会存在新的问题
ThreadLocal<Integer> InheritableThreadLocal2 = new InheritableThreadLocal<>();
// 线程池size设置为1是为了模拟线程池中的线程都已经被初始化过
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,1, 1L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(100));
threadPoolExecutor.prestartAllCoreThreads(); //预先启动所有核心线程(模拟线程池中的线程都已经被初始化过,这时候又有任务提交过来)
InheritableThreadLocal2.set(2); // 为inInheritableThreadLocal设置值
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println(InheritableThreadLocal2.get()); //输出null
}
4.使用TTL解决问题
TTL为阿里开源框架。
// 如何解决上面的问题,可以使用TTL TransmittableThreadLocal(可传递线程本地变量) 继承自InheritableThreadLocal,所以他拥有继承自InheritableThreadLocal的所有特性
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,1, 1L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(100));
threadPoolExecutor.prestartAllCoreThreads();//预先启动所有核心线程(模拟线程池中的线程都已经被初始化过,这时候又有任务提交过来)
TransmittableThreadLocal<Integer> transmittableThreadLocal = new TransmittableThreadLocal<Integer>();
transmittableThreadLocal.set(2);
// 注意。这里使用了TtlRunnable, TransmittableThreadLocal一定要搭配TTlRunnable或者TtlCallable
threadPoolExecutor.execute(TtlRunnable.get(new Runnable() {
@Override
public void run() {
System.out.println(transmittableThreadLocal.g