Java中的ThreadLocal类允许我们创建只能被同一个线程读写的变量。因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的ThreadLocal变量。
package com.zhuyang.concurrency.threadlocal;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class ThreadLocalTest2 extends Thread {
private static int num = 0;
private static Map<Thread,Integer> threadData=new HashMap<Thread,Integer>();
private static ThreadLocal<Integer> threadLocal=new ThreadLocal<Integer>();
@Override
public void run() {
int num = new Random().nextInt();
System.out.println(Thread.currentThread().getName() + " has put data, data=" + num);
threadData.put(Thread.currentThread(), num);
threadLocal.set(num);
new A().getNum();
new B().getNum();
}
public static void main(String[] args) {
for(int i=0;i<2;i++){
ThreadLocalTest2 thread = new ThreadLocalTest2();
thread.start();
}
}
static class A {
public void getNum() {
int dataFromMap = threadData.get(Thread.currentThread());
int dataFromThreadLocal = threadLocal.get();
System.out.println("A Thread " + Thread.currentThread().getName() + " has put data, dataFromMap=" + dataFromMap+",dataFromThreadLocal="+dataFromThreadLocal);
}
}
static class B {
public void getNum() {
int dataFromMap = threadData.get(Thread.currentThread());
int dataFromThreadLocal = threadLocal.get();
System.out.println("B Thread " + Thread.currentThread().getName() + " has put data, dataFromMap=" + dataFromMap+",dataFromThreadLocal="+dataFromThreadLocal);
}
}
}
执行结果:
Thread-1 has put data, data=-9946002
Thread-0 has put data, data=1910168837
A Thread Thread-1 has put data, dataFromMap=-9946002,dataFromThreadLocal=-9946002
A Thread Thread-0 has put data, dataFromMap=1910168837,dataFromThreadLocal=1910168837
B Thread Thread-0 has put data, dataFromMap=1910168837,dataFromThreadLocal=1910168837
B Thread Thread-1 has put data, dataFromMap=-9946002,dataFromThreadLocal=-9946002
结果能看出两个线程之间并不会共享数据。
源码分析:
public void set(T value) {
Thread t = Thread.currentThread();//获得当前线程
ThreadLocalMap map = getMap(t); //获取当前线程的本地变量MAP
if (map != null)
map.set(this, value);//map不为空则塞值,key为当前线程,value为值
else
createMap(t, value);//创建线程 t.threadLocals = new ThreadLocalMap(this, firstValue);
}
public T get() {
Thread t = Thread.currentThread();//获得当前线程
ThreadLocalMap map = getMap(t);//获取当前线程的本地变量MAP
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);//如果不为空,获得entry
if (e != null)
return (T)e.value;
}
return setInitialValue();//创建map
}