ThreadLocal
ThreadLocal 为线程局部变量,或许将它命名为ThreadLocalVariable更为合适。其主要作用就是实现线程本地存储功能,通过线程本地资源隔离,解决多线程并发场景下线程安全问题
如果没有 ThreadLocal 的话,就需要在各线程执行代码内部都加上大量重复代码【相同变量定义】。使用 ThreadLocal 的话,代码上复用一份,但实际各自线程维护各自局部变量数据
Java 中的 ThreadLocal 和 InheritableThreadLocal 都是用来实现线程本地存储的,它们都是线程局部变量。ThreadLocal 为每个线程提供了一个独立的变量副本,而 InheritableThreadLocal 则允许在子线程中访问父线程中设置的值。12
ThreadLocal 是一个本地线程副本变量工具类,主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无锁化的状态共享。1
InheritableThreadLocal
子线程想使用父线程的变量,如果没有 InheritableThreadLocal 的话,就需要在各子线程中复制一份变量。使用 ThreadLocal InheritableThreadLocal,子线程自动拥有父线程变量的副本
InheritableThreadLocal 继承了 ThreadLocal,此类扩展了 ThreadLocal 以提供从父线程到子线程的值的继承:当创建子线程时,子线程接收父线程具有的所有可继承线程局部变量的初始值。2
ThreadLocal 和 InheritableThreadLocal 的区别在于:ThreadLocal 只能在当前线程中共享值,而 InheritableThreadLocal 可以在当前线程和子线程之间共享值。
InheritableThreadLocal 示例
- 主线程存放数据,后面子线程读取数据,达到「共享数据」的效果,而不需要传参方式传递数据
- 主线程先放数据,创建子线程后,子线程会复制一份数据。子线程修改数据对主线程的数据无影响
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| package org.jeecg.common.util;
import cn.hutool.core.thread.threadlocal.NamedInheritableThreadLocal; import lombok.extern.slf4j.Slf4j;
import java.util.HashMap; import java.util.Map;
@Slf4j public class MainThreadShareDataUtil { private static final ThreadLocal<Map<String, Object>> shareData = new NamedInheritableThreadLocal<>("shareData");
public static synchronized void put(String key, Object value) { Map<String, Object> dataMap = shareData.get(); if(dataMap == null) { dataMap = new HashMap<>(); shareData.set(dataMap); } dataMap.put(key, value); }
public static Object get(String key) { Map<String, Object> dataMap = shareData.get(); if(dataMap == null) return null;
return dataMap.get(key); }
public static void remove() { shareData.remove(); }
public static void main(String[] args) { put("name", "zkkk"); put("age", "122"); put("class", "ddd");
System.out.println(get("name")); System.out.println(get("age")); new Thread(()->{ System.out.println(get("name")); System.out.println(get("age")); }).start(); new Thread(()->{ System.out.println(get("class")); }).start(); } }
|