InheritableThreadLocal 是 Java 中 ThreadLocal 的子类,用于解决 父子线程间值传递 的问题。与 ThreadLocal 不同,它允许子线程自动继承父线程的变量副本,特别适用于需要跨线程传递上下文信息的场景。
核心特性
继承机制:子线程创建时会自动复制父线程的 InheritableThreadLocal 值。
线程隔离:子线程修改值不会影响父线程(深拷贝副本)。
类型安全:泛型支持(如 InheritableThreadLocal)。
使用场景
传递用户身份信息(如 Session ID)
分布式链路追踪(如 Trace ID)
事务上下文传递
多线程日志标记
跨线程资源管理
javapublic class InheritableThreadLocalDemo {
private static final InheritableThreadLocal<String> context = new InheritableThreadLocal<>();
public static void main(String[] args) {
context.set("父线程的值-123");
new Thread(() -> {
System.out.println("子线程读取: " + context.get()); // 输出父线程设置的值
context.set("子线程修改的值-456"); // 修改只影响当前线程
}).start();
System.out.println("父线程读取: " + context.get()); // 仍为"父线程的值-123"
}
}
javapublic class TraceContext {
private static final InheritableThreadLocal<String> traceId = new InheritableThreadLocal<>();
// 设置当前请求的Trace ID
public static void startTrace(String id) {
traceId.set(id);
}
// 获取Trace ID(自动传递到子线程)
public static String getTraceId() {
return traceId.get();
}
// 清理资源
public static void endTrace() {
traceId.remove();
}
}
// 使用示例
public class ServiceA {
void processRequest() {
TraceContext.startTrace("TRACE-" + UUID.randomUUID());
System.out.println("ServiceA Trace: " + TraceContext.getTraceId());
// 异步处理(子线程继承Trace ID)
new Thread(() -> {
System.out.println("子服务 Trace: " + TraceContext.getTraceId()); // 输出相同Trace ID
}).start();
}
}
线程池问题
线程复用会导致旧值残留,需在任务执行前显式传递值(如上述重写 ThreadFactory)。
内存泄漏风险
始终在 finally 块中调用 remove() 清理资源:
javatry {
context.set(value);
// ...业务逻辑
} finally {
context.remove(); // 必须清理
}
对象引用
传递可变对象时,父子线程可能共享同一对象引用(需深拷贝或防御性复制)。
性能影响
频繁创建线程时,复制操作会有额外开销。
TransmittableThreadLocal(阿里开源) 专为线程池设计,通过 TtlRunnable 包装解决复用问题。
本文作者:Weee
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!