L
L
LearnJava
Search…
ThreadLocal
ThreadLocal用于保存某个线程共享变量,对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量。
  • ThreadLocal.get: 获取ThreadLocal中当前线程共享变量的值。
  • ThreadLocal.set: 设置ThreadLocal中当前线程共享变量的值。
  • ThreadLocal.remove: 移除ThreadLocal中当前线程共享变量的值。
  • ThreadLocal.initialValue: ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回此方法值。
举例:
public class ThreadLocalTest {
private static final ThreadLocal<Object> threadLocal = new ThreadLocal<Object>() {
// ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回此方法值
protected Object initialValue() {
System.out.println("调用get方法时,当前线程共享变量没有设置,调用initialValue获取默认值!当前线程" + Thread.currentThread().getName());
return "";
};
};
public static void main(String[] args) {
new Thread(new MyThread()).start();
new Thread(new MyThread()).start();
new Thread(new MyThread()).start();
new Thread(new MyThread()).start();
}
public static class MyThread extends Thread {
@Override
public void run() {
for(int i = 0; i < 5; i++) {
if("".equals(threadLocal.get())) {
threadLocal.set("a");
}else {
threadLocal.set(threadLocal.get() + "a");
}
System.out.println("currentThread:" + Thread.currentThread().getName() + ":" + threadLocal.get());
}
}
}
}
打印结果:
调用get方法时,当前线程共享变量没有设置,调用initialValue获取默认值!当前线程Thread-3
调用get方法时,当前线程共享变量没有设置,调用initialValue获取默认值!当前线程Thread-1
调用get方法时,当前线程共享变量没有设置,调用initialValue获取默认值!当前线程Thread-7
调用get方法时,当前线程共享变量没有设置,调用initialValue获取默认值!当前线程Thread-5
currentThread:Thread-5:a
currentThread:Thread-7:a
currentThread:Thread-1:a
currentThread:Thread-1:aa
currentThread:Thread-3:a
currentThread:Thread-1:aaa
currentThread:Thread-1:aaaa
currentThread:Thread-7:aa
currentThread:Thread-5:aa
currentThread:Thread-5:aaa
currentThread:Thread-5:aaaa
currentThread:Thread-5:aaaaa
currentThread:Thread-7:aaa
currentThread:Thread-1:aaaaa
currentThread:Thread-3:aa
currentThread:Thread-7:aaaa
currentThread:Thread-3:aaa
currentThread:Thread-7:aaaaa
currentThread:Thread-3:aaaa
currentThread:Thread-3:aaaaa
可以看到不同的线程调用同一个ThreadLocal变量的get方法返回值是不一样的(就是说互不影响,比如线程1将threadLocal设置成1,那么线程2get到的并并一定是1,而是取决于线程2set的值)。那么原理是怎么实现的呢,我们看下set和get的源码:
// set的时候,先获取当前线程,以当前线程做key查询map,然后对map进行新增和更新
public void set(T paramT)
{
Thread localThread = Thread.currentThread();
ThreadLocalMap localThreadLocalMap = getMap(localThread);
if (localThreadLocalMap != null) {
localThreadLocalMap.set(this, paramT);
} else {
createMap(localThread, paramT);
}
}
// 同理,get的时候,也是先获取当前线程,以当前线程做key查询map
public T get()
{
Thread localThread = Thread.currentThread();
ThreadLocalMap localThreadLocalMap = getMap(localThread);
if (localThreadLocalMap != null)
{
ThreadLocal.ThreadLocalMap.Entry localEntry = localThreadLocalMap.getEntry(this);
if (localEntry != null)
{
Object localObject = localEntry.value;
return localObject;
}
}
return setInitialValue();
}
Copy link