ThreadLocal线程局部变量
我们创建一个全局变量时,经常使用pulic static,但有些情况下我们需要一个线程局部变量,即只属于一个线程的“全局变量”。这当然可以通过读取线程号加哈希表解决,但更好的方式是使用JDK提供的线程局部变量ThreadLocal。
此外我们要知道,线程局部变量其实在服务端开发中非常常用。Tomcat使用多线程的并发模型处理请求,如果我们希望在整个请求的作用域下保存一些线程内“全局”的数据,这些数据其实就可以用线程局部变量实现;另外在调用链日志记录领域,MDC也是通过线程局部变量实现的。
ThreadLocal的使用
MyThread.java
package com.gacfox.demo;
import java.util.Random;
public class MyThread implements Runnable {
@Override
public void run() {
Random random = new Random();
Main.threadLocal.set(random.nextInt());
System.out.println(Main.threadLocal.get());
}
}
Main.java
package com.gacfox.demo;
public class Main {
public static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
Thread myThread1 = new Thread(new MyThread());
Thread myThread2 = new Thread(new MyThread());
Thread myThread3 = new Thread(new MyThread());
Thread myThread4 = new Thread(new MyThread());
Thread myThread5 = new Thread(new MyThread());
myThread1.start();
myThread2.start();
myThread3.start();
myThread4.start();
myThread5.start();
}
}
我们创建了5个线程,他们都读写了public static ThreadLocal<Integer> threadLocal,但显然他们读写的内容都是线程隔离的。
运行结果:

带默认值的线程局部变量
ThreadLocal默认是没有值的,不set时直接get返回的是null。我们可以继承ThreadLocal,覆盖一些方法,编写一个我们自己的线程局部变量类。
public class MyThreadLocal extends ThreadLocal<Integer> {
@Override
protected Integer initialValue() {
return 1;
}
}
可继承的线程局部变量
JDK还提供了InheritableThreadLocal,子线程可以继承父线程的线程局部变量。不过当然,这两个值是隔离的,也就是说线程局部变量是从父线程复制了一份给子线程。
但是如果线程局部变量的值是一个引用就要小心了,子线程如果直接使用这个引用,那么它的改动会影响到父线程,这种用法下就要考虑线程安全问题了。如果子线程覆盖了这个引用,那就没什么问题了,这两个引用是隔离的,其指向的对象也完全隔离了。
作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。