ThreadLocal类被称为线程本地变量类或者线程局部变量类。如果程序创建了一个ThreadLocal实例,那么在访问这个变量的值时,每个线程都会拥有一个独立的、自己的本地值。当线程各自操作自己的本地变量时,从而实现了线程安全。
类 :
//无参
ThreadLocal<String> threadLocal = new ThreadLocal<>();
//静态方法 withInitial 全部线程可见
ThreadLocal<String> stringThreadLocal = (() -> "ok");
1.1私有的静态内部类 ThreadLocalMap
//看出Thread线程类中有个属性threadLocals
class Thread {
//属性,存储threadLocal
threadLocals = null;
...
}
class ThreadLocalMap{
//有两个构造方法
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue);
ThreadLocalMap(ThreadLocalMap parentMap);
//储存值(重要) Entry类为ThreadLocalMap的内部类,Entry(ThreadLocal<?> k, Object v) k为虚
//引用。其中value和T referent两个属性,value储存值,referent为ThreadLocal
private Entry[] table;
}
分析ThreadLocal类中的set(T value) 方法
public void set(T value) {
//1. 由Thread类的静态方法currentThread(),获取当前线程的实例t
Thread t = ();
//2. 根据线程实例t,得到当前线程的属性ThreadLocalMap map
ThreadLocalMap map = getMap(t);
//3.判断map!=null,进入ThreadLocalMap类的set方法
if (map != null)
//3.1进入ThreadLocalMap类的set方法
(this, value);
else
//4.1 进入createMap方法
createMap(t, value);
}
set(ThreadLocal<?> key, Object value) {
// 3.2 属性赋值tab
Entry[] tab = table;
// 3.3 得到tab的大小 tab初始大小为16
int len = ;
// 3.4 的二进制 & 1111(15) 0<=i<=15
int i = & (len-1);
// 3.5 i假定3, for语句的初始tab[3],当tab[i]==null结束循环,当i=15时,返回i=0
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
//3.6 从Entry中得到,当前threadLocal对象
ThreadLocal<?> k = ();
//3.7 当前threadLocal对象与this相同,覆盖之前的值
if (k == key) {
= value;
return;
}
// 3.8 当前threadLocal对象为null
if (k == null) {
//清除无效的entry
replaceStaleEntry(key, value, i);
return;
}
}
// 3.9 i=3 ,tab[3]=new Entry(key,value)
tab[i] = new Entry(key, value);
// 3.10 tab为10时,重hash,扩容
int sz = ++size;
if (!cleanSomeSlots(i, sz) && sz >= threshold) rehash();
}
void createMap(Thread t, T firstValue) {
// 4.2 ThreadLocalMap双参构造赋值给当前线程类的属性threadLocals
= new ThreadLocalMap(this, firstValue);
}
分析ThreadLocal类中的get()方法
public T get() {
// 1.获取当前线程对象的实例
Thread t = ();
// 2.得到线程实例的threadLocals属性
ThreadLocalMap map = getMap(t);
// 为not null
if (map != null) {
// 3.1.得到当前ThreadLocal对象的Entry
e = (this);
// 3.2 Entry对象不为空
if (e != null) {
@SuppressWarnings("unchecked")
// 3.3 得到Entry对象的value值,返回
T result = (T);
return result;
}
}
// 4.会调用SuppliedThreadLocal类重写的initialValue()方法,返回value,并且会将该值和当
// 前的Threadlocal对象储存到当前线程的threadLocals中
return setInitialValue();
}
ThreadLocal对象。1,线程安全,不需要加锁,避免锁的开销。2,节省内存。因为线程储存对象值,因此对象与线程的生命周期相同。3,线程隔离。
使用时1.用static final 修饰 2.使用结束后调remove()方法。
应用。1.从数据库的connection对象,放到ThreaLocal。。将requesFadce放到放到ThreaLocal中。对象或token(携带用户基本信息)放在ThreaLocal。。将SecurityContextImpl对象放到了ThreadLocal。(线程不安全)。
2.举例
// 继承ThreadLocal类
// (()->new TestBean("34")) 把对象储存起来
// get()每次得到对象引用是一样的
// ()->new TestBean("34") get()每次得到对象引用是不一样的
public class NamedThreadLocal<T> extends ThreadLocal<T> {
private final String name;
public NamedThreadLocal(String name) {
(name, "Name must not be empty");
= name;
}
public String toString() {
return ;
}
}
// 可继承的ThreadLocal类
// 使用主线程inheritableThreadLocals(ThreadLocalMap)
// 再开启子线程时,调用子线程的init(...)方法将主线程inheritableThreadLocals值复制一份创建
// 子线程的inheritableThreadLocals(ThreadLocalMap)
// 主线程储的对象,而子线程储对象的引用(value储的值,referent为创建的原始的threadLocal)
public class InheritableThreadLocal<T> extends ThreadLocal<T> {
/**
* Computes the child's initial value for this inheritable thread-local
* variable as a function of the parent's value at the time the child
* thread is created. This method is called from within the parent
* thread before the child is started.
* <p>
* This method merely returns its input argument, and should be overridden
* if a different behavior is desired.
*
* @param parentValue the parent thread's value
* @return the child thread's initial value
*/
protected T childValue(T parentValue) {
return parentValue;
}
/**
* Get the map associated with a ThreadLocal.
*
* @param t the current thread
*/
ThreadLocalMap getMap(Thread t) {
return ;
}
/**
* Create the map associated with a ThreadLocal.
*
* @param t the current thread
* @param firstValue value for the initial entry of the table.
*/
void createMap(Thread t, T firstValue) {
= new ThreadLocalMap(this, firstValue);
}
}
// 继承继承ThreadLocal类
public class NamedInheritableThreadLocal<T> extends InheritableThreadLocal<T> {
private final String name;
public NamedInheritableThreadLocal(String name) {
(name, "Name must not be empty");
= name;
}
public String toString() {
return ;
}
}