文章目录
一. ThreadLocal
面试官经常问:“说说你对ThreadLocal的理解吧”
我们背诵的答案:
线程同步机制是多个线程共享同一个变量,而ThreadLocal是为每个线程创建一个单独的变量副本,每个线程都可以改变自己的变量副本而不影响其它线程所对应的副本
说白了就是线程级别的局部变量,内部是ThreadLocalMap结构,每个线程内部都存在一个局部变量ThreadLocal.ThreadLocalMap threadLocals = null;
,ThreadLocal的get
,set
实际操作的都是线程的局部变量threadLocals 。
Thread变量定义
class Thread implements Runnable {
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
ThreadLocal的API
方法名 | 说明 |
---|---|
get() | 返回此线程局部变量的当前线程副本中的值 |
set(T value) | 将线程局部变量当前副本中的值设置为指定值 |
remove() | 移除此线程局部变量当前副本中的值 |
get,set源码
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
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 getMap(Thread t) {
return t.threadLocals;
}
可以发现,每个线程中都有一个变量ThreadLocal.ThreadLocalMap,当执行get,set方法时都在操作当前线程的threadLocals变量,所以多个线程互不干扰。
示例
代码
public class ThreadLocalDemo {
public static final ThreadLocal userThreadLocal = new ThreadLocal();
public static final Map userMap = new HashMap<>();
public static void main(String[] args) throws InterruptedException {
for (int i=0;i<2;i++) {
// 睡一会
Thread.sleep(3000);
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("userThreadLocal:" + Thread.currentThread().getName() + ":" + userThreadLocal.get());
userThreadLocal.set(Math.random() * 100);
System.out.println("userThreadLocal:" + Thread.currentThread().getName() + ":" + userThreadLocal.get());
System.out.println("----------------");
System.out.println("userMap:" + Thread.currentThread().getName() + ":" + userMap.get("a"));
userMap.put("a", Math.random() * 100);
System.out.println("userMap:" + Thread.currentThread().getName() + ":" + userMap.get("a"));
System.out.println("====================================================");
}
}).start();
}
}
}
输出
分别定义了ThreadLocal 和Map变量,观察两个线程执行的区别,Map变量在第二个线程中获取到了第一个线程的值,而ThreadLocal 变量没有