ThreadLocal关键字与InheritableThreadLocal关键字

ThreadLocal是什么

在多线程环境下,防止自己的变量被其它线程篡改,实现单个线程的共享变量,ThreadLocal解决的就是每个线程绑定自己的变量值。

ThreadLocal源码解析

set()方法:

 public void set(T value) {
 		//取到当前的单独的线程
        Thread t = Thread.currentThread();
        //拿到t线程的threadLocals,每个线程都有一个ThreadLocalMap 
        ThreadLocalMap map = getMap(t);
        //每个线程的ThreadLocalMap默认为null 
        if (map != null)
        	//this指当前创建的ThreadLocal对象
            map.set(this, value);
        else
            createMap(t, value);
    }

get()方法:

 public T get() {
        Thread t = Thread.currentThread();
        //取到单独的线程的ThreadLocalMap,一个线程有独一无二的一个Map--ThreadLocalMap 
        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();
    }   
每个线程中都仅有一个ThreadLocalMap对象,当执行set方法时,ThreadLocal对象获取到当前线程下ThreadLocalMap对象, 
进行set操作,key为当前new出来的ThreadLocal对象,value为自定义的值,
存储数据的ThreadLocalMap对象保存在当前线程的threadLocals变量中,当执行set方法中,是从当前线程的threadLocals变量获取。
所以在线程1中set的值,对线程2来说是摸不到的,而且在线程2中重新set的话,也不会影响到线程1中的值,
保证了线程之间不会相互干扰。

ThreadLocal使用

   public static void main(String[] args) {
       //当前main线程下,new多个ThreadLocal对象,其实是向main线程的成员变量: 
       //ThreadLocal.ThreadLocalMap threadLocals中set多个值,key分别为:
       //threadLocal1,threadLocal2
        ThreadLocal threadLocal1 = new ThreadLocal();
        threadLocal.set("ceshi1");
        ThreadLocal threadLocal2 = new ThreadLocal();
        threadLocal1.set("ceshi2");
        System.out.println(threadLocal1.get());
        System.out.println(threadLocal2.get());

    }
   结果输出:ceshi1
           ceshi2

ThreadLocal内存泄露

//threadLocalMap存储的entry对象,是WeakReference弱引用
static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;
            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }
因为threadLocalMap,中的enrty对象key是弱引用(只要gc,不管内存是否充足必定会回收
,而map的value是强引用不会回收,存在内存泄露问题)

ThreadLocal内存泄露解决

try {
    //业务逻辑
} finally {
    //remove实际调用Thread线程中threadLocalMap的remove方法,删除掉不用的key,value,
    //threadLocalMap依然在.
    threadLocal对象.remove();
}

FastThreadLocal是ThreadLocal替代品,吞吐量更高,速度更快

InheritableThreadLocal关键字

InheritableThreadLocal关键字中子线程会继承父线程存储的数据。子线程可以修改继承的主线程的存储数据,且主线程的存储数据不受影响。

public class Test {
    public static InheritableThreadLocal threadLocal = new InheritableThreadLocal();
    public static void main(String[] args) throws Exception{
        threadLocal.set("主线程的值");
        System.out.println(threadLocal.get());
        Thread.sleep(3000);
        new Thread( ()-> {
            threadLocal.set("子线程的值");
            System.out.println(threadLocal.get());
        }).start();
        Thread.sleep(3000);
        System.out.println(threadLocal.get());
    }
}

运行结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值