《struts2技术内幕》中说到了TheadLocal模式的纵向隔离与横向隔离问题,这里写细一些帮助记忆
如上图每个thread中都有一个ThreadLocalMap变量,并且其中以各个ThreadLocal实例为key存着变量。
这样thread之间即为同一threadlocal类不同实例的纵向隔离。
图1
如上图每个thread中都有一个ThreadLocalMap变量,并且其中以各个ThreadLocal实例为key存着变量。
这样thread之间即为同一threadlocal类不同实例的纵向隔离。
一个thread内ThreadLocalMap根据不同ThreadLocal得到相应变量值即为横向隔离。
具体到后面的例子代码如下:
public class Counter {
// 新建一个静态的ThreadLocal变量,并通过get方法将其变为一个可访问的对象
private static ThreadLocal<Integer> counterContext = new ThreadLocal<Integer>() {
protected synchronized Integer initialValue() {
return 10;
}
};
// 通过静态的get方法访问ThreadLocal中存储的值
public static Integer get() {
return counterContext.get();
}
// 通过静态的set方法将变量值设置到ThreadLocal中
public static void set(Integer value) {
counterContext.set(value);
}
// 封装业务逻辑,操作存储于ThreadLocal中的变量
public static Integer getNextCounter() {
counterContext.set(counterContext.get() + 1);
return counterContext.get();
}
}
虽然Count中counterContext是类变量,然而在执行getNextCounter()时,threadlocal的set方法已经获得当前线程对象,并且得到线程对象中的ThreadLocalMap,将自己与要保存的值存成了图1的结构。
public class ThreadLocal<T> {
// 这里省略了许多其他代码
// 将value的值保存于当前线程的本地变量中
public void set(T value) {
// 获取当前线程
Thread t = Thread.currentThread();
// 调用getMap方法获得当前线程中的本地变量ThreadLocalMap
ThreadLocalMap map = getMap(t);
// 如果ThreadLocalMap已存在,直接使用
if (map != null)
// 以当前的ThreadLocal的实例作为key,存储于当前线程的
// ThreadLocalMap中,如果当前线程中被定义了多个不同的ThreadLocal
// 的实例,则它们会作为不同key进行存储而不会互相干扰
map.set(this, value);
else
// ThreadLocalMap不存在,则为当前线程创建一个新的
createMap(t, value);
}
// 获取当前线程中以当前ThreadLocal实例为key的变量值
public T get() {
// 获取当前线程
Thread t = Thread.currentThread();
// 获取当前线程中的ThreadLocalMap
ThreadLocalMap map = getMap(t);
if (map != null) {
// 获取当前线程中以当前ThreadLocal实例为key的变量值
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
// 当map不存在时,设置初始值
return setInitialValue();
}
// 从当前线程中获取与之对应的ThreadLocalMap
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
// 创建当前线程中的ThreadLocalMap
void createMap(Thread t, T firstValue) {
// 调用构造函数生成当前线程中的ThreadLocalMap
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
// ThreadLoaclMap的定义
static class ThreadLocalMap {
// 这里省略了许多代码
}
}