java并发编程之美 学习笔记
示例
public class MyThreadLocalTest1 {
static ThreadLocal<Integer> localVariable = new ThreadLocal<>();
static final int THREAD_NUM = 5;
static void safe(int index) {
new Thread(() ->{
localVariable.set(index);
try {
TimeUnit.SECONDS.sleep(THREAD_NUM - index);
} catch (InterruptedException e) {
}
System.out.println("thread_"+index+" 获得的值为:"+ localVariable.get());
}).start();
}
static Integer variable = -1;
static void unsafe(int index) {
new Thread(() ->{
variable = index;
try {
TimeUnit.SECONDS.sleep(THREAD_NUM - index);
} catch (InterruptedException e) {
}
System.out.println("thread_"+index+" 获得的值为:"+ variable);
}).start();
}
}
unsafe()
测试代码:
IntStream.rangeClosed(1,THREAD_NUM).forEach(index -> {
unsafe(index);
});
运行结果:
safe()
测试代码
IntStream.rangeClosed(1,THREAD_NUM).forEach(index -> {
safe(index);
});
运行结果:
源码分析
ThreadLocal类
初始化
public class ThreadLocal<T> {
public ThreadLocal() {
}
}
get()
public class ThreadLocal<T> {
public T get() {
Thread t = Thread.currentThread();
//1.
ThreadLocalMap map = getMap(t);
if (map != null) {
//获取Entry, key为this即ThreadLocal实例对象;
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
T result = (T)e.value;
return result;
}
}
//2.
return setInitialValue();
}
//1.获取当前现成的 ThreadLocalMap threadLocals属性
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
//2.若map为空,则初始化一个ThreadLocalMap并初始化到Thread的threadLocals属性中
private T setInitialValue() {
//3.
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
//4.
createMap(t, value);
return value;
}
//3.初始值默认为null,可由子类覆盖重写
protected T initialValue() {
return null;
}
//4.创建一个ThreadLocalMap,并给初始值
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
}
set()
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
//向map中设置值,key为当前ThreadLocal 实例对象;
map.set(this, value);
else
//若map为空,则创建一个,在get()中已经分析过,这里不再赘述
createMap(t, value);
}
ThreadLocalMap类
ThreadLocalMap
为ThreadLocal
的静态内部类.
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
private static final int INITIAL_CAPACITY = 16;
private int size = 0;
private Entry[] table;
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
//计算当前ThreadLocal的hash值 在“桶”中的位置.
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
//新增一个Entry
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
private Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & (table.length - 1);
Entry e = table[i];
if (e != null && e.get() == key)
//当找到正确的entry时,直接返回
return e;
else
//未正确找到时,做特殊操作(略....)
return getEntryAfterMiss(key, i, e);
}
private void set(ThreadLocal<?> key, Object value) {
Entry[] tab = table;
int len = tab.length;
//计算当前key的hash值 在“桶”中的位置.
int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
ThreadLocal<?> k = e.get();
if (k == key) {
//当“桶” i位置存在k,且与key相同时,直接更新值
e.value = value;
return;
}
if (k == null) {
//当“桶” i位置存在k,但k为空时,替换当前之前的entry
replaceStaleEntry(key, value, i);
return;
}
}
//当key不存在时,直接新增entry
tab[i] = new Entry(key, value);
int sz = ++size;
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
}
补充:ThreadLocal.threadLocalHashCode逻辑
//threadLocalHashCode 为实例变量
private final int threadLocalHashCode = nextHashCode();
private static int nextHashCode() {
//nextHashCode为静态变量,所以所有的ThreadLocal实例共享一份;
return nextHashCode.getAndAdd(HASH_INCREMENT);
}
private static AtomicInteger nextHashCode = new AtomicInteger();
private static final int HASH_INCREMENT = 0x61c88647;
此段代码可以理解为:每new一个ThreadLocal()对象,都需要将nextHashCode自增HASH_INCREMENT值作为该对象的hashCode
.
Thread类
public class Thread implements Runnable {
//每个线程对象都有threadLocals ,和 inheritableThreadLocals 成员属性;
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
}
尝试总结
每个Thread中都有可能会定义多个ThreadLocal属性,这些属性全部都被定义在一个叫做ThreadLocalMap属性中,它的结构可以看成为Map<ThreadLocal,Object>
,当我们需要get()
获取值时,会使用ThreadLocal实例对象作为key,去map中寻找对应的值并返回。
ThreadLocal使用
ThreadLocal不支持继承性
public void test() {
ThreadLocal threadLocal = new ThreadLocal();
threadLocal.set("threadLocal");
new Thread(() -> {
System.out.println("SUB---threadLocal----" + threadLocal.get());
}).start();
System.out.println("MAIN---threadLocal----" + threadLocal.get());
}
sub线程打印结果为null;
InheritableThreadLocal
InheritableThreadLocal可继承
public void test2() {
//InheritableThreadLocal 可继承
InheritableThreadLocal inheritableThreadLocal = new InheritableThreadLocal();
inheritableThreadLocal.set("inheritableThreadLocal");
new Thread(() -> {
System.out.println("SUB----inheritableThreadLocal----" + inheritableThreadLocal.get());
}).start();
System.out.println("MAIN---inheritableThreadLocal----" + inheritableThreadLocal.get());
}
执行结果:
InheritableThreadLocal类
public class InheritableThreadLocal<T> extends ThreadLocal<T> {
protected T childValue(T parentValue) {
return parentValue;
}
ThreadLocalMap getMap(Thread t) {
return t.inheritableThreadLocals;
}
void createMap(Thread t, T firstValue) {
t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
}
}
InheritableThreadLocal类相对简单,重写了getMap()和createMap
方法,与ThreadLocal的区别是,它使用的是Thread.inheritableThreadLocals
属性作为map的“载体”。
那它是如何实现可继承
性的呢,答案就在Thread
类中。
public class Thread implements Runnable {
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
//当前线程为 parent线程;
Thread parent = currentThread();
//略....
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
//如果父线程 inheritableThreadLocals 不为空,即父线程定义了 InheritableThreadLocal变量;
if (parent.inheritableThreadLocals != null)
//当前Thread的inheritableThreadLocals,则继承线程的属性
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
this.stackSize = stackSize;
tid = nextThreadID();
}
}