传递 Threadlocal 给子线程
787 字大约 3 分钟2024年12月4日
使用 InheritableThreadLocal
InheritableThreadLocal
类是 ThreadLocal
的子类,专门用于在子线程中继承父线程的 ThreadLocal
变量。它能够自动将父线程的 ThreadLocal
变量值传递给子线程。
public class InheritableThreadLocalExample {
private static final InheritableThreadLocal<String> threadLocal = new InheritableThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
threadLocal.set("Parent Thread Local Value");
Thread childThread = new Thread(() -> {
System.out.println("Child Thread: " + threadLocal.get());
});
childThread.start();
childThread.join();
System.out.println("Parent Thread: " + threadLocal.get());
}
}
手动传递 ThreadLocal
值
另一种方法是手动将父线程的 ThreadLocal
值传递给子线程。这可以通过在创建子线程时将 ThreadLocal
值作为参数传递给子线程的构造函数或任务。
public class ManualThreadLocalExample {
private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
threadLocal.set("Parent Thread Local Value");
String parentValue = threadLocal.get();
Thread childThread = new Thread(() -> {
threadLocal.set(parentValue);
System.out.println("Child Thread: " + threadLocal.get());
});
childThread.start();
childThread.join();
System.out.println("Parent Thread: " + threadLocal.get());
}
}
使用自定义 ThreadFactory
你还可以创建一个自定义的 ThreadFactory
,在创建新线程时自动传递 ThreadLocal
值。
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
public class CustomThreadFactoryExample {
private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
threadLocal.set("Parent Thread Local Value");
ThreadFactory factory = new CustomThreadFactory(threadLocal.get());
Executors.newSingleThreadExecutor(factory).execute(() -> {
System.out.println("Child Thread: " + threadLocal.get());
});
}
static class CustomThreadFactory implements ThreadFactory {
private final String parentValue;
CustomThreadFactory(String parentValue) {
this.parentValue = parentValue;
}
@Override
public Thread newThread(Runnable r) {
return new Thread(() -> {
threadLocal.set(parentValue);
r.run();
});
}
}
}
使用 TransmittableThreadLocal
TransmittableThreadLocal
是阿里巴巴开源的一个工具类,它扩展了 Java 标准库中的 InheritableThreadLocal
,使得父线程的 ThreadLocal
变量不仅能够传递给子线程,还能在使用线程池等复杂场景下进行传递。
import com.alibaba.ttl.TransmittableThreadLocal;
public class TransmittableThreadLocalExample {
private static final TransmittableThreadLocal<String> threadLocal = new TransmittableThreadLocal<>();
public static void main(String[] args) {
// 设置父线程的 ThreadLocal 变量
threadLocal.set("Parent Thread Local Value");
// 创建子线程
Thread childThread = new Thread(() -> {
// 获取子线程中的 ThreadLocal 变量
System.out.println("Child Thread: " + threadLocal.get());
});
// 启动子线程
childThread.start();
// 等待子线程结束
try {
childThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 获取父线程中的 ThreadLocal 变量
System.out.println("Parent Thread: " + threadLocal.get());
}
}
在这个示例中,子线程能够正确获取到父线程设置的 ThreadLocal
变量值,即 “Parent Thread Local Value”。
在线程池中使用 TtlRunnable
对于线程池中的任务,你可以使用 TtlRunnable
来包装任务,从而确保 TransmittableThreadLocal
变量能够正确传递。
import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.TtlRunnable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TransmittableThreadLocalThreadPoolExample {
private static final TransmittableThreadLocal<String> threadLocal = new TransmittableThreadLocal<>();
public static void main(String[] args) {
threadLocal.set("Parent Thread Local Value");
ExecutorService executorService = Executors.newFixedThreadPool(2);
Runnable task = () -> {
System.out.println("Task Thread: " + threadLocal.get());
};
// 使用 TtlRunnable 包装任务
executorService.submit(TtlRunnable.get(task));
// 关闭线程池
executorService.shutdown();
}
}