Java中ThreadLocal的使用及原理详解
作者:回家放羊吧
简介
ThreadLocal是JDK提供的,提供线程本地变量,主要用来存放线程独有变量和解决参数传递问题的。
例子
public static void main(String[] args) { ThreadLocal threadLocal = new ThreadLocal(); for(int i=0;i<3;i++){ new Thread(()->{ double random = Math.floor(Math.random()*10); threadLocal.set(random); System.out.println("设置线程"+Thread.currentThread().getName()+",线程变量:"+random); System.out.println("查看线程"+Thread.currentThread().getName()+",线程变量:"+threadLocal.get()); }).start(); } }
设置线程Thread-2,线程变量:4.0
设置线程Thread-0,线程变量:9.0
设置线程Thread-1,线程变量:5.0
查看线程Thread-0,线程变量:9.0
查看线程Thread-2,线程变量:4.0
查看线程Thread-1,线程变量:5.0
可以看出,每个线程的变量是隔离开的,避免了出现线程不安全的问题,ThreadLocal是如何实现的呢?
原理
ThreadLocalMap
public class Thread implements Runnable { ThreadLocal.ThreadLocalMap threadLocals = null; }
ThreadLocalMap是真正存储数据的地方,ThreadLocalMap在各个线程中,为线程独有的
set方法
public void set(T value) { //获取调用者线程 Thread t = Thread.currentThread(); //获取调用者线程自有的ThreadLocalMap ThreadLocalMap map = getMap(t); if (map != null) //如果map!=null直接设置值 map.set(this, value); else //创建ThreadLocalMap,并将value存储 createMap(t, value); } ThreadLocalMap getMap(Thread t) { //获取线程的ThreadLocalMap return t.threadLocals; } void createMap(Thread t, T firstValue) { //创建ThreadLocalMap,并设置firstValue t.threadLocals = new ThreadLocalMap(this, firstValue); }
从set方法中第二行代码ThreadLocalMap map = getMap(t);这段代码是获取当前线程的ThreadLocalMap,然后进行设置值,通过getMap方法可以看出,线程本地变量并不是存储在ThreadLocal,而是存储在各自线程的ThreadLocalMap threadLocals中的,ThreadLocal只是相当于一个工具类,对ThreadLocalMap进行操作而已。
get方法
public T get() { //获取调用者线程 Thread t = Thread.currentThread(); //获取调用者线程自有的ThreadLocalMap ThreadLocalMap map = getMap(t); if (map != null) { //获取到当前ThreadLocal的值 ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); } private T setInitialValue() { //获取默认值(null),也可以重写该方法 T value = initialValue(); //获取调用者线程 Thread t = Thread.currentThread(); //获取调用者线程自有的ThreadLocalMap ThreadLocalMap map = getMap(t); if (map != null) //设置为空 map.set(this, value); else //创建一个ThreadLocalMap,赋值为空 createMap(t, value); return value; }
get方法是获取当前线程的ThreadLocalMap,然后通过将ThreadLocal当做key,从ThreadLocalMap中获取到相应的Entry,Entry里包含了key和value,最后将value返回,如果没有key的值,就会调用setInitialValue方法,setInitialValue方法会初始化一个默认值,默认值是null,也可以重写initialValue,获得自己想要的默认值,如果没有创建ThreadLocalMap,则创建,然后返回默认值
remove方法
public void remove() { //获取调用者线程自有的ThreadLocalMap ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) //删除ThreadLocalMap中key为当前ThreadLocal的数据 m.remove(this); }
remove方法十分简单,就是删除ThreadLocalMap中key为当前ThreadLocal的数据
总结
通过看源码,可以得出
- ThreadLcoal只是一个用来操作ThreadLocalMap的一个工具类和充当ThreadLocalMap的key。
- ThreadLocalMap是真正存储数据的,但是ThreadLocalMap是存储在每个线程中的。
- 每个线程都有各自的ThreadLocalMap,这也是实现线程隔离的根本原因。
到此这篇关于Java中ThreadLocal的使用及原理详解的文章就介绍到这了,更多相关ThreadLocal的使用及原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!