ThreadLocal变量,字面意思理解是"线程局部变量"的意思,它实现的功能是:一个线程内部共享,不同线程之间是隔离的,每个线程只能get()到自己的变量。
看下面的ThreadLocal变量的使用代码
public class ThreadLocalTest {
private static ThreadLocal<Integer> num = new ThreadLocal<>();
public static void main(String[] args){
num.set(0);
//创建线程1号
new Thread(new Runnable() {
@Override
public void run() {
num.set(1);
System.out.println("一号线程中ThreadLocal变量值保存为: "+num.get());
}
},"1").start();
//创建2号线程
new Thread(new Runnable() {
@Override
public void run() {
num.set(2);
System.out.println("二号线程中ThreadLocal变量值保存为:"+num.get());
}
},"2").start();
//为了让二号线程执行完毕,主线程休眠500ms
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程中ThreadLocal保存的值为:"+num.get());
}
}
表面看,num是是静态的,存储在常量池,主线程获取的时候,应该会被修改为1或者2(线程1和线程2调度决定哪个线程先执行),但是打印结果为:
一号线程中ThreadLocal变量值保存为: 1
二号线程中ThreadLocal变量值保存为:2
主线程中ThreadLocal保存的值为:0
各个线程get到的为自己存储的值,这是为什么?需要看下ThreadLocal变量的get()和set()源码实现。
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocal.ThreadLocalMap map = this.getMap(t);
if (map != null) {
/**
* 关键,this为当前ThreadLocal对象,存储时,是为每个线程建一个map
* 将当前的ThreadLocal对象作为map的key,存储到当前线程的map中
*/
map.set(this, value);
} else {
this.createMap(t, value);
}
}
以上代码为ThreadLocal变量set方法API,注释为本人添加,通过源码可以知道,在set时,并没有将值直接保存到ThreadLocal对象,而是为每个线程新建了map,将ThreadLocal变量当前的对象(调用set方法的对象),作为key,值作为map的value来存储,这样实现了不同线程之间的隔离,同一个线程之间的共享。