ThreadLocal是什么和有什么用
ThreadLocal这个类提供线程本地的变量。这些变量与一般正常的变量不同,它们在每个线程中都是独立的。ThreadLocal实例最典型的运用就是在类的私有静态变量中定义,并与线程关联。
Synchronized用于线程间的数据共享,保证高并发的时候不会出现脏读问题;而ThreadLocal则用于线程间的数据隔离,每个线程都拥有一份独立的数据。所以ThreadLocal的应用场合,最适合的是按线程多实例(每个线程对应一个实例)的对象的访问,并且这个对象很多地方都要用到。
Demo
public class ThreadLocalTest {
public static ThreadLocal<String> threadLocalMap = new ThreadLocal<>();
public static void main(String[] args) throws Exception{
threadLocalMap.set("main");
Thread t = new Thread(new Runnable() {
@Override
public void run() {
threadLocalMap.set("thread");
}
});
t.start();
//保证线程t执行完才sout
t.join();
//最后输出的是“main”
System.out.println(threadLocalMap.get());
}
}
按照以往的经验,我们是先set("main"),再set("thread"),那么应该输出的是后面set的"thread",这里却输出的是“main”。这是为什么呢?我们可以把threadLocal看做是以线程为key的map,但是这个map只能存放一个value。因为每个每个线程的key肯定不一样,所以取出value也不一样。即如果你在t的run方法里面get的话,那么输出的应该是"thread"。
源码解析
ThreadLocal --> set()
public class ThreadLocal<T> {
public void set(T value) {
Thread t = Thread.currentThread();
//map是当前线程的对象的一个成员变量threadLocals,可以把它看做是一个map,不过是以当threadLocal为key
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
}
class Thread implements Runnable {
ThreadLocal.ThreadLocalMap threadLocals = null;
}
ThreadLocal --> get()
public class ThreadLocal<T> {
public T get() {
Thread t = Thread.currentThread();
//跟1.7之前的hashmap其实有点像
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
}
网友评论