ThreadLocal的功能及应用场景
0x01 是什么
JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序,ThreadLocal并不是一个Thread,而是Thread的局部变量。
ThreadLocal翻译过来叫:线程本地变量
ThreadLocal不是用于解决共享变量的问题的,不是为了协调线程同步而存在,而是为了方便每个线程处理自己的状态而引入的一个机制
0x02 源码分析
public ThreadLocal(); //创建一个线程本地变量
public T get(); //返回当前线程的线程变量值,若没有值则调用initialValue()方法
public void set(T value); //将此线程局部变量的当前线程副本中的值设置为指定值
public void remove(); //移除此线程局部变量的值
protected T initialValue(); //返回该线程局部变量的初始值1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
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 void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
protected T initialValue() {
return null;
}
从源码中可以看出,在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。
0x03 常用案例
下面是看一个hibernate中典型的ThreadLocal的应用:1
2
3
4
5
6
7
8
9
10
11
12
13
14private static final ThreadLocal threadSession = new ThreadLocal();
public static Session getSession() throws InfrastructureException {
Session s = (Session) threadSession.get();
try {
if (s == null) {
s = getSessionFactory().openSession();
threadSession.set(s);
}
} catch (HibernateException ex) {
throw new InfrastructureException(ex);
}
return s;
}