ThreadLocal从字面意思来看是线程本地(变量),有什么作用呢?
存放在ThreadLocal中的变量值只在当前线程中可见及使用。那仅在当前线程可用,自然就不存在多线程并发冲突问题,是一种空间(每个线程单独存储变量)换时间的解决多线程并发问题的方式。
下面举例说明:
package threadLocalDemo; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Demo { static ThreadLocal<String> threadLocal = new ThreadLocal<>(); public static void main(String[] args) throws InterruptedException { //创建一个仅有一个线程的线程池(模拟在一个线程中的前后操作) ExecutorService executorService = Executors.newFixedThreadPool(1); //线程提交任务:线程中设置ThreadLocal变量并打印 executorService.submit(() -> { threadLocal.set("hello"); System.out.println(Thread.currentThread().getName()+":"+threadLocal.get()); }); //线程延迟1s提交任务:获取ThreadLocal变量并打印 Thread.sleep(1000); executorService.submit(() -> { System.out.println(Thread.currentThread().getName()+":"+threadLocal.get()); }); //线程延迟1s提交任务:获取ThreadLocal变量并打印 Thread.sleep(1000); executorService.submit(() -> { System.out.println(Thread.currentThread().getName()+":"+threadLocal.get()); }); executorService.shutdown(); } }
打印结果如下:
pool-1-thread-1:hello pool-1-thread-1:hello pool-1-thread-1:hello
说明只要在当前线程中设置ThreadLocal变量后,线程的后续操作时都可以拿到此变量。
另外:在某些场景下,我们在同一线程的前后操作中是需要修改或者清空ThreadLocal变量的,当然也有相关的API,举例如下:
package threadLocalDemo; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class AnotherDemo { static ThreadLocal<String> threadLocal = new ThreadLocal<>(); public static void main(String[] args) throws InterruptedException { //创建一个仅有一个线程的线程池(模拟在一个线程中的前后操作) ExecutorService executorService = Executors.newFixedThreadPool(1); //线程提交任务:线程中设置ThreadLocal变量并打印 executorService.submit(() -> { threadLocal.set("hello"); System.out.println(Thread.currentThread().getName()+":"+threadLocal.get()); }); //线程延迟1s提交任务:获取ThreadLocal变量并打印 Thread.sleep(1000); executorService.submit(() -> { //修改变量 threadLocal.set("world"); System.out.println(Thread.currentThread().getName()+":"+threadLocal.get()); //删除变量 threadLocal.remove(); }); //线程延迟1s提交任务:获取ThreadLocal变量并打印 Thread.sleep(1000); executorService.submit(() -> { System.out.println(Thread.currentThread().getName()+":"+threadLocal.get()); }); executorService.shutdown(); } }
打印结果如下:
pool-1-thread-1:hello pool-1-thread-1:world pool-1-thread-1:null