Understanding ThreadLocal in Java: Creation, Usage, and Implementation Details
This article explains Java's ThreadLocal class, covering its purpose for thread‑local storage, core methods such as get, set, and remove, ways to set initial values via subclassing or withInitial, usage of InheritableThreadLocal for parent‑child thread data propagation, and the underlying implementation details.
Java provides the ThreadLocal class to enable thread‑local storage, allowing variables to be isolated to the thread that creates them. This eliminates the need for synchronization when data is not shared across threads.
The class is defined in java.lang.ThreadLocal and offers several key methods:
T get() – retrieves the current thread's copy of the variable.
void set(T value) – sets the current thread's copy.
void remove() – deletes the current thread's copy.
T initialValue() – provides a default value (null by default) which can be overridden.
static ThreadLocal withInitial(Supplier supplier) – creates a ThreadLocal with a custom initial value.
Typical usage involves creating a ThreadLocal instance, optionally specifying a generic type to avoid casting, and then calling set and get within the same thread:
private ThreadLocal
myThreadLocal = new ThreadLocal<>();
myThreadLocal.set("Hello ThreadLocal");
String value = myThreadLocal.get();To provide a custom initial value, you can either subclass ThreadLocal and override initialValue() or use the static withInitial factory method. The latter can be expressed with an anonymous class or a lambda expression:
private ThreadLocal
threadLocal = ThreadLocal.withInitial(() -> (int) System.currentTimeMillis());When a child thread needs access to the parent thread's ThreadLocal data, InheritableThreadLocal (a subclass of ThreadLocal ) should be used. It propagates the value from the parent to the child thread via the overridden childValue method.
ThreadLocal
threadLocal = new ThreadLocal<>();
InheritableThreadLocal
inheritable = new InheritableThreadLocal<>();
// In parent thread
threadLocal.set("Parent TL");
inheritable.set("Parent Inheritable");
// In child thread, threadLocal.get() returns null, inheritable.get() returns "Parent Inheritable"Internally, each Thread holds a ThreadLocalMap that stores entries as weak references to the ThreadLocal keys and strong references to the values. The map uses linear probing to resolve hash collisions, differing from the chaining approach of a typical HashMap .
Understanding these mechanisms helps answer common interview questions about thread‑local storage and its interaction with other concurrency primitives such as volatile .
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.