ThreadLocal,InheritableThreadLocal,TTL全解

ThreadLocal,InheritableThreadLocal,TTL全解


一、ThreadLoal 详解

ThreadLocal 是保存线程的使用变量。
ThreadLocal具体方法如下:
在这里插入图片描述

public class ThreadLocal<T> {
    
    /**
     * 1.8以后提供的,返回一个有初始值的ThreadLocal
     */
    public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
        return new SuppliedThreadLocal<>(supplier);
    }

  
    /**
     * 获取当前线程保存的变量
     */
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

   
    /**
     * 设置当前线程的值
     */
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

    /**
     * 清除当前线程的值:当前线程退出时,最后要调用一下清除方法。
     */
     public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }

 

    /**
     * 创建一个ThreadLocalMap,多个线程保存变量个关键的关键
     */
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

}

通过以代码可以看到ThreadLocalMap是每个线程持有的。所以保证线程隔离。ThreadLocalMap中key使用的使用的弱引用,在相同GC时,就会被清理掉。threadLocal生命周期里会尽可能的保证不出现内存泄漏的问题,达到安全的状态。
在这里插入图片描述那么ThreadLocal会有内存泄露的问题吗?答案是会的。避免内存泄露的方法,是在使用完ThreadLocal后,要调用remove方法,将其清除掉。

二、InheritableThreadLocal 详解

InheritableThreadLocal 用于子线程创建时,自动继承父线程的ThreadLocal变量。

在这里插入图片描述
可以看出InheritableThreadLocal 是继承ThreadLocal并重写了其中的3个方法。实现子线程获取父线程的变量,是在Thread的初始化的时候。
在这里插入图片描述
默认是TRUE,也就是在这里插入图片描述
初始化的时候,将父线程的所以变量都遍历复制一遍,这也子线程就自动的获取到父线程的值了。
注意:InheritableThreadLocal在线程池使用的时候,就会失效。如果想用线程池,可以考虑使用阿里的TTL

三、阿里TTL的使用

阿里的transmittable-thread-local简称TTL,TTL继承并加强InheritableThreadLocal类。
典型使用场景
分布式跟踪系统
应用容器或上层框架跨应用代码给下层SDK传递信息
日志收集记录系统上下文
使用类TransmittableThreadLocal来保存上下文,并跨线程池传递。TransmittableThreadLocal继承InheritableThreadLocal,使用方式也类似。比InheritableThreadLocal,添加了protected方法copy,用于定制 任务提交给线程池时的上下文传递到 任务执行时时的拷贝行为,缺省是传递的是引用。

可以说TTL是InheritableThreadLocal的加强版。使用方法:

  1. 使用com.alibaba.ttl.TtlRunnable和com.alibaba.ttl.TtlCallable来修饰传入线程池的Runnable和Callable。
  2. 省去每次Runnable和Callable传入线程池时的修饰,这个逻辑可以在线程池中完成。
    通过工具类com.alibaba.ttl.threadpool.TtlExecutors完成,有下面的方法:
    getTtlExecutor:修饰接口Executor
    getTtlExecutorService:修饰接口ExecutorService
    ScheduledExecutorService:修饰接口ScheduledExecutorService
  3. 使用Java Agent来修饰JDK线程池实现类

总结

通过以上分析,结合不同的场景,应用不同的ThreadLocal,达到自己的目的。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值