ThreadLocal的理解

本文主要准备通过以下四个方面对ThreadLocal进行分析和说明

  1. 概要说明
  2. ThreadLocal使用
  3. 原理
  4. GC回收

1. 概要说明

举个不是很恰当的例子,如果把线程比作一个人,那么ThreadLocalMap就是他身上的所有口袋,每个口袋(ThreadLocal)可以放不同的工具(数据),无论这个人走到哪儿,他都可以使用自己口袋里面的工具

看一下代码

Thread.java内部里面持有一个map

/* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;

可以看到这个ThreadLocalMap是ThreadLocal的一个内部类,注释上也表明这个map的维护工作是通过ThreadLocal这个类进行了。所以我们大概也可以猜测,通过ThreadLocal的调用,最后把一些变量放入到当前线程的ThreadLocalMap内部。

2. ThreadLocal的使用

先用一个简单的Main方法,只是new了一个ThreadLocal变量,这里main所在的主线程向threadLocal里面添加一个数字,看看发生了什么。

public class ThreadLocalTest {

    public static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();

    public static void main(String[] args) {
        threadLocal.set(1);
        System.out.println(threadLocal.get());
    }

}

threadLocal的set方法:

前两行,获取当前线程,还记得线程中有一个threadLocalMap吧,获取到这个map。

然后判断是否为空,空则创建一个ThreadLocalMap,不为空则set进去变量。

然后这个map的key是this,value就不用说了。this指的是当前ThreadLocal变量实例,所以就算有多个线程,对于每个线程来说,内部都有一个自己的map,key是ThreadLocal实例。那么如果有多个ThreadLocal变量呢?可以参考下图:

3. 原理

让我们看看ThreadLocal类的代码:

首先看到的是3个变量

threadLocalHashCode

nextHashCode

HASH_INCREMENT

这几个变量有什么用,我们可以猜测一下。首先看起来是和hashCode相关的,然后

private final int threadLocalHashCode = nextHashCode();

这段代码,意味着每次初始化一个ThreadLocal变量,都会通过nextHashCode()这个方法生成一个hashCode,这个hashCode是通过一个static的原子变量getAndAdd(HASH_INCREMENT)得到的

private static AtomicInteger nextHashCode =
    new AtomicInteger();

static意味着全局唯一,所以我们每new一个ThreadLocal对象,这个对象内部会持有一个唯一的hashCode,至于为什么增量是0x61c88647,看下注释,是为了在2的幂次方长度的hashtable得到更好的分布。

ThreadLocal核心方法:

setInitialValue() 为threadLocal变量设置初始值,防止get()空指针

get()、set(), remove(), 获取/设置/移除 threadLocalMap中的变量。

4. GC回收

正常情况下,由于变量最终是存在Thread类的ThreadLocalMap变量内的,所以线程执行结束后,随着线程对象的回收,threadLocalMap也会被正常回收掉,但是如果是线程池的模式,线程执行完成,没有被回收掉,threadLocalMap对象也不会被回收,可能会导致内存泄漏。

所以正确的打开方式是,使用完ThreadLocal变量,手动调用一下ThreadLocal.remove()方法进行清理。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值