目录
ThreadLocal类 简介
1、ThreadLocal 可以实现在同一个线程数据共享, 从而解决多线程数据安全问题
2、ThreadLocal 可以使用set 方法给当前线程关联一个数据【普通变量、对象、数组】
3、ThreadLocal 可以像 Map 一样存取数据,其中key 为当前线程, value 为当前线程关联的那个数据
4、每一个 ThreadLocal 对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数据,就需要使用多个 ThreadLocal 对象实例
5、每个 ThreadLocal 对象实例定义的时候,一般为 static 类型
6、ThreadLocal 中保存数据,在线程销毁后,会自动释放
ThreadLocal 类的方法
常用方法
//创建ThreadLocal对象
public static ThreadLocal<Object> myThreadLocal = new ThreadLocal<>();
//给 myThreadLocal对象 关联一个数据
myThreadLocal.set(object);
//取出 myThreadLocal对象 关联的数据
myThreadLocal.get();
//删除 myThreadLocal对象 关联的数据
myThreadLocal.remove();
set()和get()方法 源码解读
//set()解读
public void set(T value) {
//1. 获取当前线程, 关联到当前线程
Thread t = Thread.currentThread();
//2. 通过线程对象, 获取到ThreadLocalMap
// ThreadLocalMap :
//(ThreadLocal类 的静态内部类,也是在这里使ThreadLocalMap里只有一个Entry节点)
ThreadLocalMap map = getMap(t);
//3. 如果map不为null, 将数据(普通变量、对象、数组) 放入map
// 重复set, 原先的数据就会被替换
//4. 如果map为null, 就创建一个和当前线程关联的ThreadLocalMap, 并且该数据放入
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
//get()解读
public T get() {
//1. 先得到当前的线程对象
Thread t = Thread.currentThread();
//2.通过线程获取到对应的ThrealLocalMap
ThreadLocalMap map = getMap(t);
if (map != null) {
//3. 如果map不为空, 根据当前的 threadlocal对象, 得到对应的Entry
ThreadLocalMap.Entry e = map.getEntry(this);
//4. 如果e 不为null, 返回当前threadlocal关联的数据value
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
简单案例
MyThreadlocal类的 Test内部类 与 C1类、C2类 三个类 使用同一个同一个线程里的threadLocal对象 进行数据共享操作
MyThreadlocal类
public class MyThreadlocal {
public static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
public static class Test implements Runnable{
@Override
public void run() {
Integer integer = new Integer(999);
threadLocal.set(integer);
System.out.println("Test 放入了 integer= " + integer);
System.out.println("Test 的run()方法中的线程为:" + Thread.currentThread().getName()
+ " integer= " + integer);
new C1().method_C1();
}
}
public static void main(String[] args) {
new Thread(new Test()).start();
}
}
C1类
public class C1 {
public void method_C1(){
Integer integer = MyThreadlocal.threadLocal.get();
System.out.println("在C1的method_C1() 中的线程name= " +
Thread.currentThread().getName() + " integer= " + integer);
new C2().method_C2();
}
}
C2类
public class C2 {
public void method_C2(){
Integer integer = MyThreadlocal.threadLocal.get();
System.out.println("在C2的method_C2() 中的线程name= " +
Thread.currentThread().getName() + " integer= " + integer);
}
}
运行结果: