ThreadLocal源码分析

通过java.lang.ThreadLocal类,可以实现线程本地存储。

添加操作

1
2
3
4
5
6
7
8
9
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
// 如果当前线程的threadLocals属性已经被初始化,则直接添加
if (map != null)
map.set(this, value);
else
createMap(t, value);
}

1.getMap(t)的源码如下:

1
2
3
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}

2.声明threadLocals变量的源码如下:

1
2
3
4
5
public class Thread implements Runnable {
// 包访问权限:ThreadLocal与Thread在同一包中(java.lang)
ThreadLocal.ThreadLocalMap threadLocals = null;
...
}

3.第一次向当前线程中存放数据时,将执行createMap()方法,创建ThreadLocal.ThreadLocalMap对象。

1
2
3
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}

取值操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
// 如果当前线程的threadLocals字段已经被初始化
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
// 如果能找到该项
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
// 如果map尚未初始化,或者没找到该项,则将默认值插入map中并返回
return setInitialValue();
}

1.如果当前线程中没有存放过数据(实例变量threadLocals尚未初始化),或者在哈希表中没有找到该项,则执行setInitialValue()方法,源码如下:

1
2
3
4
5
6
7
8
9
10
11
private T setInitialValue() {
// 获取默认值
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}

2.方法initialValue()的源码如下:

1
2
3
4
// 默认值为null,如果需要自定义默认值,只需重写该方法即可
protected T initialValue() {
return null;
}

删除操作

1
2
3
4
5
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}

----------本文结束感谢您的阅读----------
坚持原创技术分享,您的支持将鼓励我继续创作!