ThreadLocal
线程容器,给线程绑定一个 Object
内容,后只要线程不变,可以随时 取出.。改变线程则无法取出内容
public static void main(String[] args) {
final ThreadLocal<String> threadlocal = new ThreadLocal<>();
threadlocal.set("测试");
String result = threadlocal.get();
System.out.println(result);
new Thread() {
public void run() {
String result = threadlocal.get();
System.out.println(result);
};
}.start();
}
作用
ThreadLocal,即线程变量,它将需要并发访问的资源复制多份,让每个线程拥有一份资源。 由于每个线程都拥有自己的资源副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享机制,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。
在实现上:
Thread类中声明了ThreadLocal.ThreadLocalMap类型的threadLocals变量,用于存放当前线程独占的资源。ThreadLocalMap,这是一个类似于Map的结构,用于存放键值对。
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal类还提供了set和get方法, set方法会初始化ThreadLocalMap并将其绑定到Thread.threadLocals上,从而将传入的值绑定到当前线程。在数据存储上,ThreadLocal对象本身(this)当做key,传入的值将作为键值对的value。
// 以下为自己整合的源代码、非源代码原貌
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = t.threadLocals;
if (map != null)
map.set(this, value);
else
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
get方法没有任何参数,它会以当前ThreadLocal对象(this)为key,从Thread.threadLocals中获取与当前线程绑定的数据。
// 以下为自己整合的源代码、非源代码原貌
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = t.threadLocals;
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 = null;
Thread t = Thread.currentThread();
ThreadLocalMap map = t.threadLocals;
if (map != null)
map.set(this, value);
else
t.threadLocals = new ThreadLocalMap(this, value);
return value;
}
加分回答 :
ThreadLocal不能替代同步机制,两者面向的问题领域不同。 同步机制是为了同步多个线程对相同资源的并发访问,是多个线程之间进行通信的有效方式。 而ThreadLocal是为了隔离多个线程的数据共享,从根本上避免多个线程之间对共享资源(变量)的竞争,也就不需要对多个线程进行同步了。
一般情况下,如果多个线程之间需要共享资源,以达到线程之间的通信功能,就使用同步机制。 如果仅仅需要隔离多个线程之间的共享冲突,则可以使用ThreadLocal。