在阅读源代码或多线程应用中,我们经常会看到ThreadLocal类,本文带你了解ThreadLocal。
ThreadLocal简介
在多线程的情况下,一个共享变量可能被多个线程修改,导致数据的不安全性,ThreadLocal就是为了解决这种问题,为每个线程提供该线程专属的本地变量。
我们可以简单理解成,往ThreadLocal放入一个变量,ThreadLocal会为每个线程都准备一个副本变量。这样就避免了多个线程对同一个变量的操作。
ThreadLocal 用法示例
![2cd43d3fc2bbcbef3636a21848e7c20e.png](https://img-blog.csdnimg.cn/img_convert/2cd43d3fc2bbcbef3636a21848e7c20e.png)
输出结果为:
![e8cbeb7b3e7018d6cd7e5961d4ac2644.png](https://img-blog.csdnimg.cn/img_convert/e8cbeb7b3e7018d6cd7e5961d4ac2644.png)
可以看到,每个线程的 ThreadLocal.get和set设置和获取到的值都是互相不干扰的。
ThreadLocal的原理
ThreadLocal最重要的方法就是set()和get(),我们就从这两个方法的源码开始。
先来看下set方法
![a89aee61170090db995e59840468d331.png](https://img-blog.csdnimg.cn/img_convert/a89aee61170090db995e59840468d331.png)
ThreadLocal.set()
可以看到,set方法还是比较简单的,首先通过Thread.currentThread()获取当前线程,然后通过getMap(),并传入当前线程,获取到ThreadLocalMap对象,我们暂时可以先行把ThreadLocalMap理解成map,当map不为空,直接将当前对象当做key,将值设置如map,如果map不存在,创建map并设置值。
再来看下getMap方法
![3efb5e12cf29569062f51d55d4ccafd8.png](https://img-blog.csdnimg.cn/img_convert/3efb5e12cf29569062f51d55d4ccafd8.png)
直接返回了线程的thradLocal属性,我们再来看下Thread的threadlocals属性
![52a3906b0ba640b6b1c25e9753d97fe0.png](https://img-blog.csdnimg.cn/img_convert/52a3906b0ba640b6b1c25e9753d97fe0.png)
threadLocals属性是一个ThreadLocal.ThreadLocalMap对象,由ThreadLocal维护,Thread对象并不适用。
好了,再来看一下ThreadLocalMap对象,ThreadLocalMap是ThreadLocal的一个内部类,有以下属性:
![07408cd39ba5a5bdcc71f605a98c552f.png](https://img-blog.csdnimg.cn/img_convert/07408cd39ba5a5bdcc71f605a98c552f.png)
再来看一下ThreadLocalMap的set方法
![4acb7a86fec78c5dfdc1010f30174e3c.png](https://img-blog.csdnimg.cn/img_convert/4acb7a86fec78c5dfdc1010f30174e3c.png)
看完后,如果大家看过HashMap的源代码,对ThreadLocalMap应该有点印象了,采用的是拉链法进行存储,table存储的是散列表,通过key的hash值取余,如果取余值存在,在下一位存入,如果不存在,直接存入。
好了,看完set,再来看get方法
![c89f132928fb18c0e11f3f337444a621.png](https://img-blog.csdnimg.cn/img_convert/c89f132928fb18c0e11f3f337444a621.png)
get方法,比较简单,获取ThreadLocalmap,并获取值。
最后,一图解释上面过程
![ea16fea8e7f34eb281feeeb7d5697214.png](https://img-blog.csdnimg.cn/img_convert/ea16fea8e7f34eb281feeeb7d5697214.png)
ThreadLocal获取当前线程,然后操作将值存入当前线程的ThreadLocalMap对象,由于每个线程都有ThreadLocalMap对象,互不干扰,所以是线程安全的。