3.5 ThreadLocal
相比做java的就算没用过ThreadLocal也一定听过ThreadLocal,因为它太有名了,它能够实现线程间隔离,资源只被创建该资源的线程获取,是不是很神奇,接下来就将探讨ThreadLocal的神秘所在。
3.5.1 ThreadLocal的用法
package thrd;
public class ThreadLocalDemo {
private ThreadLocal<String> str = new ThreadLocal<>();
public static void main(String[] args) {
ThreadLocalDemo threadLocalDemo = new ThreadLocalDemo();
threadLocalDemo.str.set("hello");
System.err.println(threadLocalDemo.str.get());
new Thread(()->{
System.err.println("其他线程获取:"+threadLocalDemo.str.get());
}).start();
}
}
使用set方法来为ThreadLocal对象设置值,get方法来获取该ThreadLocal对象的值,并且可以看到,当其他对象去获取该ThreadLocal的值的时候获取到的值为null,这也印证了ThreadLocal的作用,只有为该对象设置值的线程可以获取到该值。
3.5.2 ThreadLocal原理
set方法
public void set(T value) {
Thread t = Thread.currentThread();
// ThreadLocalMap
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
//如果map为null,则初始化Map并将将当前线程和值作为Key-Value传入
createMap(t, value);
}
获取当前线程,以当前线程为key获取到了一个ThreadLocalMap,当该Map不为null,将当前线程和设置的值以Key-Value的形式放入到这个ThreadLocalMap中,如果该Map为null,则初始化Map并将将当前线程和值作为Key-Value传入。那么为什么不同线程获取到的值不一样呢?
答案就在getMap(t)方法里,说明不同线程获取到的不是同一个ThreadLocalMap,那么他们获取到的值就当然不一样了!该方法获取到的是当前线程的一个属性threadLocals。
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
该Map是作为Thread类的一个成员属性,所以不同线程获取到的不一样。
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
get方法
public T get() {
Thread t = Thread.currentThread();
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();
}
先获取到当前线程的ThreadLocalMap,然后再该Map中获取到对应的值,ThreadLocal的实现是不是很简单!
感谢阅读,欢迎与在下交流讨论