Passing Threadlocal to child threads
Using InheritableThreadLocal
The InheritableThreadLocal
class is a subclass of ThreadLocal
designed specifically to allow ThreadLocal
variables to be inherited by child threads. It automatically passes the ThreadLocal
variable value from the parent thread to the child threads.
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());
}
}
Manually Passing ThreadLocal
Values
Another approach is to manually pass the ThreadLocal
value from the parent thread to the child thread. This can be done by passing the ThreadLocal
value as a parameter to the child thread's constructor or task when it is created.
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());
}
}
Using a Custom ThreadFactory
You can also create a custom ThreadFactory
to automatically pass the ThreadLocal
values when new threads are created.
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();
});
}
}
}
Using TransmittableThreadLocal
TransmittableThreadLocal
is an open-source tool from Alibaba that extends the InheritableThreadLocal
class from the Java standard library, allowing ThreadLocal
variables in the parent thread to not only be passed to child threads but also across thread pools and other complex scenarios.
import com.alibaba.ttl.TransmittableThreadLocal;
public class TransmittableThreadLocalExample {
private static final TransmittableThreadLocal<String> threadLocal = new TransmittableThreadLocal<>();
public static void main(String[] args) {
// Set the ThreadLocal variable in the parent thread
threadLocal.set("Parent Thread Local Value");
// Create a child thread
Thread childThread = new Thread(() -> {
// Get the ThreadLocal variable in the child thread
System.out.println("Child Thread: " + threadLocal.get());
});
// Start the child thread
childThread.start();
// Wait for the child thread to finish
try {
childThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Get the ThreadLocal variable in the parent thread
System.out.println("Parent Thread: " + threadLocal.get());
}
}
In this example, the child thread correctly receives the ThreadLocal
variable value set by the parent thread, which is "Parent Thread Local Value".
Using TtlRunnable
in Thread Pools
For tasks in thread pools, you can use TtlRunnable
to wrap the tasks, ensuring that the TransmittableThreadLocal
variables are correctly passed.
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());
};
// Wrap the task with TtlRunnable
executorService.submit(TtlRunnable.get(task));
// Shutdown the thread pool
executorService.shutdown();
}
}