在Java多线程编程中,线程间数据隔离是一个常见需求。ThreadLocal提供了线程本地存储的能力,而InheritableThreadLocal则在此基础上增加了父子线程间的值传递功能。
InheritableThreadLocal的核心在于Thread类的两个关键字段:
java复制public class Thread implements Runnable {
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
}
当创建新线程时,Java会检查父线程的inheritableThreadLocals是否为空。如果不为空,则会通过ThreadLocal.createInheritedMap()方法创建一个新的ThreadLocalMap,并将父线程的值复制到子线程中。
这个复制过程发生在Thread.init()方法中:
java复制private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
Thread parent = currentThread();
if (inheritThreadLocals && parent.inheritableThreadLocals != null) {
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
}
}
关键提示:继承只发生在子线程创建时,后续父线程值的修改不会自动同步到已创建的子线程。
通过一个简单示例可以清晰看到两者的区别:
java复制public class ThreadLocalComparison {
private static final ThreadLocal<String> regularThreadLocal = new ThreadLocal<>();
private static final InheritableThreadLocal<String> inheritableThreadLocal =
new InheritableThreadLocal<>();
public static void main(String[] args) {
// 主线程设置值
regularThreadLocal.set("Regular Value");
inheritableThreadLocal.set("Inheritable Value");
// 创建子线程
new Thread(() -> {
System.out.println("子线程获取:");
System.out.println("RegularThreadLocal: " + regularThreadLocal.get()); // null
System.out.println("InheritableThreadLocal: " + inheritableThreadLocal.get()); // Inheritable Value
}).start();
}
}
输出结果验证了:
InheritableThreadLocal通过重写三个关键方法实现继承功能:
java复制public class InheritableThreadLocal<T> extends ThreadLocal<T> {
// 决定如何从父值派生子值
protected T childValue(T parentValue) {
return parentValue;
}
// 获取线程的inheritableThreadLocals而非普通threadLocals
ThreadLocalMap getMap(Thread t) {
return t.inheritableThreadLocals;
}
// 创建新的inheritableThreadLocals Map
void createMap(Thread t, T firstValue) {
t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
}
}
当创建子线程时,会调用ThreadLocal.createInheritedMap()方法:
java复制static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
ThreadLocalMap map = new ThreadLocalMap(parentMap);
// 其他初始化...
return map;
}
这个构造函数会遍历父线程的所有Entry,并为每个Entry调用childValue()方法获取子值:
java复制private ThreadLocalMap(ThreadLocalMap parentMap) {
Entry[] parentTable = parentMap.table;
int len = parentTable.length;
setThreshold(len);
table = new Entry[len];
for (int j = 0; j < len; j++) {
Entry e = parentTable[j];
if (e != null) {
ThreadLocal<Object> key = (ThreadLocal<Object>) e.get();
if (key != null) {
// 关键点:调用childValue方法
Object value = key.childValue(e.value);
Entry c = new Entry(key, value);
table[j] = c;
size++;
}
}
}
}
在Web应用中,经常需要在异步处理中保持用户身份信息:
java复制public class UserContextHolder {
private static final InheritableThreadLocal<User> currentUser =
new InheritableThreadLocal<>();
public static void setCurrentUser(User user) {
currentUser.set(user);
}
public static User getCurrentUser() {
return currentUser.get();
}
public static void clear() {
currentUser.remove();
}
}
// 使用示例
public class OrderService {
public void asyncProcessOrder(Order order) {
User user = getCurrentUserFromRequest();
UserContextHolder.setCurrentUser(user);
try {
// 主线程处理
processOrder(order);
// 异步处理日志
CompletableFuture.runAsync(() -> {
// 子线程仍能获取用户信息
auditLog(UserContextHolder.getCurrentUser(), order);
});
} finally {
UserContextHolder.clear();
}
}
}
构建全链路追踪系统时,需要传递traceId和spanId:
java复制public class TraceContext {
private static final InheritableThreadLocal<Trace> currentTrace =
new InheritableThreadLocal<>();
public static void startTrace() {
Trace trace = new Trace(generateTraceId(), generateSpanId());
currentTrace.set(trace);
}
public static Trace getCurrentTrace() {
return currentTrace.get();
}
public static void endTrace() {
currentTrace.remove();
}
private static String generateTraceId() {
return UUID.randomUUID().toString();
}
private static String generateSpanId() {
return UUID.randomUUID().toString().substring(0, 8);
}
public static class Trace {
private final String traceId;
private final String spanId;
// constructor, getters...
}
}
在某些特殊场景下,可能需要子线程共享父线程的数据库连接:
java复制public class TransactionContext {
private static final InheritableThreadLocal<Connection> connectionHolder =
new InheritableThreadLocal<>();
public static void bindConnection(Connection conn) {
connectionHolder.set(conn);
}
public static Connection getConnection() {
return connectionHolder.get();
}
public static void unbindConnection() {
Connection conn = connectionHolder.get();
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
// 处理异常
}
}
connectionHolder.remove();
}
}
// 使用示例
public class BatchProcessor {
public void processInParallel(List<Data> dataList) {
Connection conn = dataSource.getConnection();
TransactionContext.bindConnection(conn);
try {
// 主线程工作
processMainData();
// 并行处理子任务
dataList.parallelStream().forEach(data -> {
// 子线程获取连接
try (Statement stmt = TransactionContext.getConnection().createStatement()) {
// 使用连接处理数据
}
});
} finally {
TransactionContext.unbindConnection();
}
}
}
重要提示:这种共享连接的方式需要谨慎使用,确保线程安全性和正确的连接生命周期管理。
通过重写childValue()方法,可以控制值的继承方式:
java复制public class PrefixInheritableThreadLocal extends InheritableThreadLocal<String> {
private final String prefix;
public PrefixInheritableThreadLocal(String prefix) {
this.prefix = prefix;
}
@Override
protected String childValue(String parentValue) {
return prefix + parentValue;
}
}
// 使用示例
public class CustomInheritDemo {
public static void main(String[] args) {
PrefixInheritableThreadLocal local = new PrefixInheritableThreadLocal("Child-");
local.set("ParentValue");
new Thread(() -> {
System.out.println(local.get()); // 输出: Child-ParentValue
}).start();
}
}
对于可变对象,可能需要深拷贝以避免共享状态:
java复制public class DeepCopyInheritableThreadLocal<T extends Serializable>
extends InheritableThreadLocal<T> {
@Override
protected T childValue(T parentValue) {
try {
// 通过序列化实现深拷贝
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(parentValue);
oos.close();
ByteArrayInputStream bais =
new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return (T) ois.readObject();
} catch (Exception e) {
throw new RuntimeException("Deep copy failed", e);
}
}
}
确保子线程不能修改继承的值:
java复制public class ReadOnlyInheritableThreadLocal<T> extends InheritableThreadLocal<T> {
@Override
protected T childValue(T parentValue) {
if (parentValue instanceof List) {
return (T) Collections.unmodifiableList(new ArrayList<>((List<?>) parentValue));
}
if (parentValue instanceof Map) {
return (T) Collections.unmodifiableMap(new HashMap<>((Map<?, ?>) parentValue));
}
return parentValue;
}
}
线程池场景下,线程会被复用,导致上下文混乱:
java复制public class ThreadPoolProblemDemo {
private static final InheritableThreadLocal<String> context =
new InheritableThreadLocal<>();
private static final ExecutorService executor = Executors.newFixedThreadPool(2);
public static void main(String[] args) throws InterruptedException {
// 任务1
context.set("Task1-Context");
executor.submit(() -> {
System.out.println("Task1: " + context.get()); // 正确输出
});
Thread.sleep(100);
// 任务2
context.set("Task2-Context");
executor.submit(() -> {
// 可能输出Task1的上下文!
System.out.println("Task2: " + context.get());
});
executor.shutdown();
}
}
确保每次任务执行后清理ThreadLocal:
java复制public class ManualCleanupSolution {
private static final InheritableThreadLocal<String> context =
new InheritableThreadLocal<>();
private static final ExecutorService executor = Executors.newFixedThreadPool(2);
public static void submitTask(String taskContext) {
executor.submit(() -> {
try {
context.set(taskContext);
// 实际任务处理
System.out.println("Processing: " + context.get());
} finally {
context.remove(); // 关键清理操作
}
});
}
}
阿里巴巴的TransmittableThreadLocal提供了更完善的解决方案:
java复制public class TtlSolution {
private static final TransmittableThreadLocal<String> context =
new TransmittableThreadLocal<>();
private static final ExecutorService executor =
TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(2));
public static void main(String[] args) {
// 任务1
context.set("Task1-Context");
executor.submit(() -> {
System.out.println("Task1: " + context.get());
});
// 任务2
context.set("Task2-Context");
executor.submit(() -> {
System.out.println("Task2: " + context.get()); // 保证正确
});
}
}
InheritableThreadLocal使用不当会导致内存问题:
java复制public class MemoryBestPractice {
// 不推荐 - 存储大数组
private static final InheritableThreadLocal<byte[]> badExample =
new InheritableThreadLocal<>();
// 推荐 - 存储轻量级对象
private static final InheritableThreadLocal<String> goodExample =
new InheritableThreadLocal<>();
public void processRequest(Request request) {
try {
goodExample.set(request.getSessionId());
// 处理逻辑
} finally {
goodExample.remove(); // 必须清理
}
}
}
通过基准测试比较不同实现的开销:
java复制@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class ThreadLocalBenchmark {
private static final ThreadLocal<String> regularThreadLocal = new ThreadLocal<>();
private static final InheritableThreadLocal<String> inheritableThreadLocal =
new InheritableThreadLocal<>();
@Benchmark
public void testRegularThreadLocal(Blackhole bh) {
regularThreadLocal.set("value");
new Thread(() -> {
bh.consume(regularThreadLocal.get());
}).start();
}
@Benchmark
public void testInheritableThreadLocal(Blackhole bh) {
inheritableThreadLocal.set("value");
new Thread(() -> {
bh.consume(inheritableThreadLocal.get());
}).start();
}
}
典型测试结果:
根据具体需求选择合适的技术方案:
code复制是否需要线程间传递数据?
├── 否 → 使用ThreadLocal
└── 是 → 线程创建方式是什么?
├── 新线程 → InheritableThreadLocal
└── 线程池 → TransmittableThreadLocal
当子线程没有获取到预期的继承值时,检查:
java复制public class InheritanceCheck {
public static void checkInheritance() {
InheritableThreadLocal<String> local = new InheritableThreadLocal<>();
// 正确顺序:先设置再创建线程
local.set("value");
Thread t = new Thread(() -> {
System.out.println(local.get()); // 输出value
});
// 错误顺序:先创建线程再设置
Thread t2 = new Thread(() -> {
System.out.println(local.get()); // 输出null
});
local.set("value");
}
}
InheritableThreadLocal可能引起的内存泄漏表现:
诊断方法:
解决方案:
典型症状:
解决方案:
java复制executor.submit(() -> {
try {
// 任务逻辑
} finally {
context.remove();
}
});
java复制public class ContextAwareRunnable implements Runnable {
private final Runnable task;
private final Map<InheritableThreadLocal<?>, ?> contextSnapshot;
public ContextAwareRunnable(Runnable task) {
this.task = task;
this.contextSnapshot = captureContext();
}
private Map<InheritableThreadLocal<?>, ?> captureContext() {
// 实现上下文捕获逻辑
}
@Override
public void run() {
try {
restoreContext();
task.run();
} finally {
clearContext();
}
}
}
阿里巴巴的TransmittableThreadLocal解决了三个核心问题:
基本用法:
java复制// 初始化
TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();
// 线程池使用
ExecutorService executorService = Executors.newFixedThreadPool(3);
ExecutorService ttlExecutorService = TtlExecutors.getTtlExecutorService(executorService);
// 任务提交
context.set("value");
ttlExecutorService.submit(() -> {
System.out.println(context.get()); // 正确获取值
});
在Web环境中,Spring提供了RequestContextHolder:
java复制// 获取当前请求属性
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
// 在子线程中重新绑定
new Thread(() -> {
RequestContextHolder.setRequestAttributes(attributes);
// 处理逻辑
}).start();
实现原理:
日志上下文管理方案:
java复制try (CloseableThreadContext.Instance ctc = CloseableThreadContext.put("key", "value")) {
// 在此范围内的日志会自动包含上下文
logger.info("Message with context");
}
特点:
在订单处理流程中应用InheritableThreadLocal:
java复制public class OrderProcessingPipeline {
private static final InheritableThreadLocal<OrderContext> orderContext =
new InheritableThreadLocal<>();
public void processOrder(Order order) {
OrderContext context = new OrderContext(order);
orderContext.set(context);
try {
// 验证阶段
new Thread(this::validateOrder).start();
// 库存检查
new Thread(this::checkInventory).start();
// 支付处理
new Thread(this::processPayment).start();
} finally {
orderContext.remove();
}
}
private void validateOrder() {
OrderContext context = orderContext.get();
// 使用上下文进行验证
}
// 其他方法...
}
经验教训:
构建跨服务的调用链追踪:
java复制public class DistributedTracer {
private static final InheritableThreadLocal<Trace> currentTrace =
new InheritableThreadLocal<>();
public static <T> T trace(String operation, Supplier<T> supplier) {
Trace parentTrace = currentTrace.get();
Trace childTrace = new Trace(parentTrace);
currentTrace.set(childTrace);
try {
return supplier.get();
} finally {
currentTrace.remove();
}
}
public static void asyncTrace(String operation, Runnable task) {
Trace traceToPass = currentTrace.get();
new Thread(() -> {
currentTrace.set(traceToPass);
try {
task.run();
} finally {
currentTrace.remove();
}
}).start();
}
}
关键设计点:
在金融系统中使用InheritableThreadLocal的特殊考虑:
java复制public class TradingEngine {
private static final InheritableThreadLocal<TradingSession> tradingSession =
new InheritableThreadLocal<>();
public void executeTrade(TradeRequest request) {
TradingSession session = createSession(request);
tradingSession.set(session);
try {
// 风险检查
new Thread(this::riskCheck).start();
// 执行交易
new Thread(this::execute).start();
// 结算准备
new Thread(this::settle).start();
} finally {
tradingSession.remove();
auditLog(session);
}
}
// 其他方法...
}
Java 19引入的虚拟线程(Virtual Threads)对ThreadLocal的影响:
java复制// 虚拟线程使用示例
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
InheritableThreadLocal<String> local = new InheritableThreadLocal<>();
local.set("main-value");
executor.submit(() -> {
System.out.println(local.get()); // 输出?
});
}
在Reactive编程模型中的替代方案:
java复制public class ReactiveContext {
private static final ThreadLocal<String> CONTEXT = new ThreadLocal<>();
public Mono<String> processWithContext(Mono<String> input) {
return input.contextWrite(ctx -> {
String value = CONTEXT.get();
return ctx.put("contextKey", value);
});
}
public static void main(String[] args) {
CONTEXT.set("main-value");
new ReactiveContext()
.processWithContext(Mono.just("data"))
.flatMap(data -> {
// 在另一个线程中获取上下文
return Mono.deferContextual(ctx -> {
String contextValue = ctx.get("contextKey");
return Mono.just(data + "-" + contextValue);
});
})
.subscribe(System.out::println);
}
}
Java 19结构化并发提案与上下文管理:
java复制void handleOrder() throws ExecutionException, InterruptedException {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
InheritableThreadLocal<String> local = new InheritableThreadLocal<>();
local.set("order123");
Future<String> inventory = scope.fork(() -> {
// 可以访问inheritable thread local
return checkInventory(local.get());
});
Future<String> payment = scope.fork(() -> {
return processPayment(local.get());
});
scope.join();
scope.throwIfFailed();
System.out.println("Inventory: " + inventory.resultNow());
System.out.println("Payment: " + payment.resultNow());
}
}
将InheritableThreadLocal封装为上下文对象:
java复制public class SystemContext {
private static final InheritableThreadLocal<SystemContext> instance =
new InheritableThreadLocal<>() {
@Override
protected SystemContext initialValue() {
return new SystemContext();
}
};
private User currentUser;
private Locale locale;
private TimeZone timeZone;
public static SystemContext getCurrent() {
return instance.get();
}
public static void setCurrent(SystemContext context) {
instance.set(context);
}
public static void reset() {
instance.remove();
}
// getters and setters...
}
使用方式:
java复制// 初始化上下文
SystemContext context = new SystemContext();
context.setCurrentUser(request.getUser());
SystemContext.setCurrent(context);
try {
// 业务处理
new Thread(() -> {
// 子线程可以访问上下文
auditLog(SystemContext.getCurrent().getCurrentUser());
}).start();
} finally {
SystemContext.reset();
}
为线程添加上下文安全检查:
java复制public class SecureThread extends Thread {
private final Runnable task;
private final SystemContext context;
public SecureThread(Runnable task) {
this.task = task;
this.context = SystemContext.getCurrent();
}
@Override
public void run() {
SystemContext previous = SystemContext.getCurrent();
try {
SystemContext.setCurrent(context);
SecurityManager.checkPermission(context.getRequiredPermission());
task.run();
} finally {
SystemContext.setCurrent(previous);
}
}
}
使用AOP自动管理上下文生命周期:
java复制@Aspect
@Component
public class ContextAspect {
@Around("@annotation(withinContext)")
public Object manageContext(ProceedingJoinPoint pjp, WithinContext withinContext)
throws Throwable {
SystemContext previous = SystemContext.getCurrent();
SystemContext newContext = createNewContext(withinContext);
try {
SystemContext.setCurrent(newContext);
return pjp.proceed();
} finally {
SystemContext.setCurrent(previous);
newContext.cleanup();
}
}
private SystemContext createNewContext(WithinContext annotation) {
// 根据注解配置创建上下文
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface WithinContext {
String value() default "default";
}
验证InheritableThreadLocal行为的基本测试:
java复制public class InheritableThreadLocalTest {
private InheritableThreadLocal<String> testLocal;
@BeforeEach
void setUp() {
testLocal = new InheritableThreadLocal<>();
}
@AfterEach
void tearDown() {
testLocal.remove();
}
@Test
void shouldInheritValueFromParentThread() throws InterruptedException {
testLocal.set("parent-value");
AtomicReference<String> childValue = new AtomicReference<>();
Thread childThread = new Thread(() -> {
childValue.set(testLocal.get());
});
childThread.start();
childThread.join();
assertEquals("parent-value", childValue.get());
}
@Test
void shouldNotSeeParentModificationAfterCreation() throws InterruptedException {
testLocal.set("initial-value");
AtomicReference<String> childValue = new AtomicReference<>();
Thread childThread = new Thread(() -> {
childValue.set(testLocal.get());
});
childThread.start();
testLocal.set("modified-value");
childThread.join();
assertEquals("initial-value", childValue.get());
}
}
测试线程池场景下的行为:
java复制public class ThreadPoolIntegrationTest {
private ExecutorService executor;
private InheritableThreadLocal<String> context;
@BeforeEach
void setUp() {
executor = Executors.newFixedThreadPool(2);
context = new InheritableThreadLocal<>();
}
@AfterEach
void tearDown() {
executor.shutdownNow();
}
@Test
void shouldNotLeakContextBetweenTasks() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(2);
AtomicInteger correctCount = new AtomicInteger();
// 任务1
context.set("task1");
executor.execute(() -> {
if ("task1".equals(context.get())) {
correctCount.incrementAndGet();
}
context.remove();
latch.countDown();
});
// 任务2
context.set("task2");
executor.execute(() -> {
if ("task2".equals(context.get())) {
correctCount.incrementAndGet();
}
context.remove();
latch.countDown();
});
latch.await();
assertEquals(2, correctCount.get());
}
}
使用JMH进行基准测试:
java复制@State(Scope.Thread)
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class ThreadLocalBenchmark {
private ThreadLocal<String> regularThreadLocal;
private InheritableThreadLocal<String> inheritableThreadLocal;
@Setup
public void setup() {
regularThreadLocal = new ThreadLocal<>();
inheritableThreadLocal = new InheritableThreadLocal<>();
}
@Benchmark
public void regularThreadLocal(Blackhole bh) {
regularThreadLocal.set("value");
new Thread(() -> {
bh.consume(regularThreadLocal.get());
}).start();
}
@Benchmark
public void inheritableThreadLocal(Blackhole bh) {
inheritableThreadLocal.set("value");
new Thread(() -> {
bh.consume(inheritableThreadLocal.get());
}).start();
}
}
防止子线程修改父线程上下文:
java复制public class ImmutableContext {
private static final InheritableThreadLocal<ImmutableMap<String, Object>> context =
new InheritableThreadLocal<>() {
@Override
protected ImmutableMap<String, Object> childValue(ImmutableMap<String, Object> parentValue) {
return parentValue;
}
};
public static void initialize(Map<String, Object> values) {
context.set(ImmutableMap.copyOf(values));
}
public static Object get(String key) {
return context.get().get(key);
}
// 没有提供修改方法
}
验证上下文完整性:
java复制public class SecureContext {
private static final InheritableThreadLocal<SignedContext> context =
new InheritableThreadLocal<>();
private static final SecretKey signingKey;
static {
// 初始化签名密钥
signingKey = generateSigningKey();
}
public static void setContext(Map<String, String> values) throws GeneralSecurityException {
SignedContext signedContext = new SignedContext(values, signingKey);
context.set(signedContext);
}
public static Map<String, String> getVerifiedContext() throws SecurityException {
SignedContext signedContext = context.get();
if (signedContext == null) {
return Collections.emptyMap();
}
return signedContext.verifyAndGetValues(signingKey);
}
private static class SignedContext implements Serializable {
private final byte[] serializedValues;
private final byte[] signature;
SignedContext(Map<String, String> values, SecretKey key) throws GeneralSecurityException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(values);
}
this.serializedValues = baos.toByteArray();
this.signature = sign(this.serializedValues, key);
}
Map<String, String> verifyAndGetValues(SecretKey key) throws SecurityException {
if (!verify(serializedValues, signature, key)) {
throw new SecurityException("Context tampering detected");
}
try (ObjectInputStream ois =
new ObjectInputStream(new ByteArrayInputStream(serializedValues))) {
return (Map<String, String>) ois.readObject();
}
}
}
}
记录所有上下文访问:
java复制public class AuditedInheritableThreadLocal<T> extends InheritableThreadLocal<T> {
private final Logger auditLogger = LoggerFactory.getLogger("CONTEXT_AUDIT");
@Override
public void set(T value) {
auditLogger.info("Setting value: {}", maskSensitive(value));
super.set(value);
}
@Override
public T get() {
T value = super.get();
auditLogger.info("Accessing value: {}", maskSensitive(value));
return value;
}
@Override
public void remove() {
auditLogger.info("Clearing value");
super.remove();
}
private Object maskSensitive(T value) {
// 实现敏感信息脱敏逻辑
}
}
逐步迁移到InheritableThreadLocal的方案:
java复制public class CompatibleThreadLocal<T> {
private final ThreadLocal<T> threadLocal;
private final InheritableThreadLocal<T> inheritableThreadLocal;
private final boolean inheritable;
public CompatibleThreadLocal(boolean inheritable) {
this.inheritable = inheritable;
if (inheritable) {
this.inheritableThreadLocal = new InheritableThreadLocal<>();
this.threadLocal = null;
} else {
this.threadLocal = new ThreadLocal<>();
this.inheritableThreadLocal = null;
}
}
public void set(T value) {
if (inheritable) {
inheritableThreadLocal.set(value);
} else {
threadLocal.set(value);
}
}
public T get() {
return inheritable ? inheritableThreadLocal.get() : threadLocal.get();
}
public void remove() {
if (inheritable) {
inheritableThreadLocal.remove();
} else {
threadLocal.remove();
}
}
}
java复制public class ThreadLocalConfig {
private static boolean globalInheritable = false;
public static void setGlobalInheritable(boolean inheritable) {
globalInheritable = inheritable;
}
public static <T> CompatibleThreadLocal<T> createThreadLocal() {
return new CompatibleThreadLocal<>(globalInheritable);
}
}
针对Java 8等老版本的注意事项:
内存泄漏风险:
线程池支持:
序列化行为:
与常见框架的集成要点:
java复制@Configuration
public class ThreadLocalConfig {
@Bean
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public UserContext userContext() {
return new UserContext();
}
}
@Component
public class ContextAwareBean {
private static final InheritableThreadLocal<UserContext> contextHolder =
new InheritableThreadLocal<>();
@Autowired
public ContextAwareBean(UserContext userContext) {
contextHolder.set(userContext);
}
public void asyncOperation() {
new Thread(() -> {
UserContext context = contextHolder.get();
// 使用上下文
}).start();
}
}
java复制public class ThreadLocalSessionUtil