前言
相信不少小伙伴都知道ThreadLocal
这个知识点,或者在面试中被问道过,
知识点
ThreadLocal是什么? ThreadLocal的用法以及应用场景 ThreadLocal源码角度分析 ThreadLocal存在的问题以及解决方案
1.概念
ThreadLocal
线程局部变量,又有人称线程本地副本,在多线程环境下,如果是共享的数据,我们可以使用volatile
,synchronized
,lock
等方式处理。如果是线程自己的变量副本,每个线程直接操作自己的本地副本即可。此时就可以使用 ThreadLocal
了
2.ThreadLocal的用法以及应用场景
public class ThreadLocalDemo {
public static void main(String[] args) {
Task task = new Task();
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
}
static class Task implements Runnable{
ThreadLocal<Integer> txId = new ThreadLocal<>();
@Override
public void run() {
txId.set((int)(Math.random()*10));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(txId.get());
}
}
}
每个线程使用ThreadLocal中自己的数据,
3.ThreadLocal源码解析
3.1.set方法
public void set(T value) {
Thread t = Thread.currentThread();
//获取到ThreadLocalMap
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
//这里获取的线程`Thread`属性`threadLocals`
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
我们从线程Thread
类中找到了如下代码
/* 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;
也就是说线程 Thread
类有一个ThreadLocalMap
的熟悉来维护ThreadLocal
,也就是说我们通过线程类的一个map来维护这个副本变量的。
3.2.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();
}
get的值同上,获取到指定map直接获取相关value即可
公众号