ThreadLocal的实现原理

ThreadLocal的实现原理

​ ThreadLocal 如何保证这些对象只被当前线程访问呢?下面让我们一起深入 ThreadLocal
的内部实现。
​ 我们需要关注的自然是 ThreadLocal的set()方法和get()方法。先从set()方法说起:

public void set (T value) {
    Thread t=Thread.currentThread ();
    ThreadLocalMap map = getMap(t);
    if (map != null)
   		map.set (this, value);
    else
    	createMap(t, value);
}

​ 在set时,首先获得当前线程对象,然后通过 getMap()方法拿到线程的 ThreadLocalMap,并将值存入ThreadLocalMap 中。而 ThreadLocalMap 可以理解为一个Map(虽然不是,但是你可以把它简单地理解成HashMap),但是它是定义在Thread内部的成员。注意下面的定义是从Thread类中摘出来的:

ThreadLocal.ThreadLocalMap threadLocals = null;

​ 而设置到 ThreadLocal 中的数据,也正是写入了 threadLocals 的这个Map。其中,key为ThreadLocal当前对象,value就是我们需要的值。而threadLocals 本身就保存了当前自己所在线程的所有“局部变量”,也就是一个ThreadLocal变量的集合。

​ 在进行get()方法操作时,自然就是将这个Map中的数据拿出来。

public T get() {
    Thread t=Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
    	ThreadLocalMap.Entry e = map.getEntry(thís);
    if (e != null)
    	return (T)e.value;
    }
    return setInitialValue();
}

​ get()方法先取得当前线程的ThreadLocalMap 对象,然后通过将自己作为key取得内部
的实际数据。
​ 在了解了ThreadLocal的内部实现后,我们自然会引出一个问题:那就是这些变量是维护在Thread类内部的(ThreadLocalMap定义所在类),这也意味着只要线程不退出,对象的引用将一直存在。
当线程退出时,Thread类会进行一些清理工作,其中就包括清理 ThreadLocalMap,注、意下述代码的加粗部分:

/**
*在线程退出前,由系统回调;进行资源清理
*/
private void exit(){
    if (group != null) {
        group.threadTerminated(this);
        group = null;
    }
    target = null;
    
    /* 加速资源清理 */
    threadLocals = nu11;
    inheri tableThreadLocals = nu1l;
    
    inheritedAccessControlContext = null;
    blocker =null;
    uncaughtExceptionHandler = null;
}

​ 因此,使用线程池就意味着当前线程未必会退出(比如固定大小的线程池,线程总是存在)。如果这样,将一些大的对象设置到ThreadLocal中(它实际保存在线程持有的threadLocals Map内),可能会是系统出现内存泄漏的可能(设置了对象到ThreadLocal中,但是不清理它,在使用几次后,这个对象也不再有用了,但是它确无法被回收)。

​ 此时,如果你希望及时回收对象,最好使用ThreadLocal.remove()方法将这个变量移除。就像我们习惯性的关闭数据库连接一样。如果你确实不需要这个对象了,就应该告诉虚拟机把它回收,防止内存泄漏。

​ 另外一种情况是JDK也可能允许你像释放普通变量一样释放ThreadLocal。比如,有时我们为了加速垃圾回收,会特意写出类似obj=null的代码。同理,如果对于ThreadLocal的变量,我们也手动将其设置为null,比如tl=null,那么ThreadLocal对应的所有线程的局部变量都有可能被回收。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值