1.我们先来聊聊ThreadLocal的里边自定义的 "hashCode " (即: threadLocalHashCode ),他俩作用一样,所以第一次看源码,你就不要浪费时间在它身上,你就可以把它当做是 "hashCode "
简单说明 threadLocalHashCode 生成原理: ThreadLocal 里边存在下边这三个东西
// 1.静态字段,为类所有,所有对象共享这个一个
private static AtomicInteger nextHashCode = new AtomicInteger();
//2.常量字段,每一个对象创建之初会被赋值
private final int threadLocalHashCode = nextHashCode();
//3.静态方法, 他的作用有两个: 第一个作用: 给常量字段 threadLocalHashCode 赋值; 第二个作用 :更新公共变量nextHashCode 的值;
private static int nextHashCode() {
return nextHashCode.getAndAdd(HASH_INCREMENT);
}
以上三个犬牙交错,导致最终的一个结果,如果你懒得分析,你就只需要明白一个结果就行了:那就是使用 ThreadLocal 这个类不仅可以创建对象,还可以创建多个对象,并且这每个对象都有一个常量字段 threadLocalHashCode,而且不同对象的常量字段threadLocalHashCode 的值还不一样;
这个结果也可以简单理解为,每个 ThreadLocal 对象都有一个 threadLocalHashCode 并且他们的 threadLocalHashCode 值还不一样, 其实说到这里,你肯定觉得 ThreadLocal 的作者闲的蛋疼, 本来每个对象的 hashCode 都可以不一样,为啥非要搞个threadLocalHashCode ,这个你不要纠结,他本质上和 hashCode 在后边的使用上没有太大区别,只是ThreadLocal 的作者发现他的threadLocalHashCode 比 hashCode 用着更好(散列性好);
2.接下来我们聊聊 ThreadLocal 里边的内部类 ThreadLocalMap 是的,如果你愿意,你可以把它当成一个简单的 HashMap,但是要注意这TM是个内部类,这不是一个对象,换句话来说,这个 ThreadLocalMap 虽然在ThreadLocal 内部定义,但是并不是在ThreadLocal 对象中 保存这个集合对象, 这个集合对象在哪保存着呢? 是在线程里边,每个线程里边都有一个 ThreadLocalMap :
ThreadLocal.ThreadLocalMap threadLocals = null;
如果你觉得绕,那你可以简单理解: 就是 这个ThreadLocal 的作者,他觉得HashMap 不好用, 然后自己定义了一个ThreadLocalMap,但是此人又比较低调,所有没有把它放出来,而是把他放到了 ThreadLocal 类里边, 其实呢这个类放到哪儿都行;
3.最后要放大招了: 每个线程里边都有一个 threadLocals 这个是一个 ThreadLocal.ThreadLocalMap 类型的集合对象,这个集合对象当然是个双列集合,它的 key 就是 ThreadLocal对象, 他的值就是你用这个ThreadLocal放入的值; 不要慌,容我理一下:
其实我们为了理解清楚,可以假设下边一段代码:
public static void main(String[] args) {
final ThreadLocal<Object> threadLocal_1 = new ThreadLocal<Object>(); //创建 一个ThreadLocal对象threadLocal_1
final ThreadLocal<Object> threadLocal_2 = new ThreadLocal<Object>(); //再创建一个ThreadLocal对象threadLocal_2
for (int i = 0; i <2 ; i++) {
new Thread(new Runnable() {
public void run() {
//threadLocal_1 设置值,其实此时此刻是 threadLocal_1 给当前线程说,你过来,你不是持有一个集
//合对象 threadLocals 吗? 我把自己作为 key, 通过set方法 给你一个值 value 和我对应,你保存一下;
//那不就是相当于 每一个线程都 会拿threadLocal_1 作为key保存一个value
// 一个 threadLocal_1对象,可以在每个线程的 threadLocals 集合中作为key 存储数据 value
// 也就是说每个线程的 threadLocals 集合中都有以 threadLocal_1 为key 的一条记录 (threadLocal_1 ,value)
// 当然你不要误以为, ThreadLocal 和 线程是 一对多的关系 ,他们不是1对多的关系,
// 因为同一个线程的 threadLocals 集合对象可以存储多个(key,value) 他们可以是这种情形
// (threadLocal_1 ,value1), (threadLocal_2 ,value2), (threadLocal_3 ,value3)
// 此时此刻不是一个线程 对应多个 ThreadLocal 对象吗? 所以他们最终是多对多的关系
threadLocal_1.set(Thread.currentThread().getName());
threadLocal_2.set(Thread.currentThread().getId());
Object name = threadLocal_1.get();
System.out.println(name);
Object id = threadLocal_2.get();
System.out.println(id);
}
}).start();
}
他的结果是:
Thread-0
Thread-1
12
13
我上边的代码注释已经说得很清楚了
ps: 附上一张图:看能不能帮助理解