ThreadLocal是在多线程中处理共享变量的一种方法,通过给每个线程分配一个共享变量的副本来解决线程不安全问题
具体来说,在java中,每个线程Thread类存在一个名为threadLocals的ThreadLocalMap数据结构,用来存储这个独属这个线程的数据。
ThreadLocal中有三个核心方法:
-
get()方法:这里就是从
ThreadLocalMap中读取需要的值 -
set()方法:这里就是将共享变量副本存入
ThreadLocalMap中 -
remove()方法:这里就是从
ThreadLocalMap中移除副本变量
注意,ThreadLocal变量的生命周期和线程的生命周期无关,也就是说,即使线程已经结束,如果没有调用过remove()方法,那么这个ThreadLocal变量依然存在
一般来说,处理共享变量的线程不安全问题,更好的解决办法是使用@synchronized关键字。
示例代码:
// 创建一个类实现Runable接口,并实现run方法来实现多线程
public class Test implements Runnable {
// 定义ThreadLocal变量
private final ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
// 实现一个子线程
@Override
public void run () {
System.out.println("进入子线程");
threadLocal.set((int) (Math.random() * 100));
System.out.println("Thread Id: " + Thread.currentThread().getId() + " - Value: " + threadLocal.get());
// 如果不调用remove, 那么即使线程结束,这个变量也不会释放,也就是说它的生命周期和创建它的线程无关
threadLocal.remove();
}
public static void main(String[] args) throws InterruptedException {
Test test = new Test();
// 创建三个线程
Thread thread1 = new Thread(test);
Thread thread2 = new Thread(test);
Thread thread3 = new Thread(test);
thread1.start(); // 线程的状态切换为RUNABLE
thread2.start();
thread3.start();
thread1.join(); // 等待这个线程执行完毕
thread2.join();
thread3.join();
}
}
多线程知识回顾:
在java实现多线程的时候,一定是通过start()方法启动,如果直接调用run()方法, 那么依然是在当前线程执行,而非子线程
如果先调用join(), 而不是start(), 那么当前线程可能会去等待一个不存在的子线程,可能发生死锁。