get or set method) has its own, independently initialized
copy of the variable. ThreadLocal instances are typically private
static fields in classes that wish to associate state with a thread (e.g.,
a user ID or Transaction ID).
For example, the class below generates unique identifiers local to each
thread.
A thread's id is assigned the first time it invokes ThreadId.get()
and remains unchanged on subsequent calls.
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadId {
// Atomic integer containing the next thread ID to be assigned
private static final AtomicInteger nextId = new AtomicInteger(0);
// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId =
new ThreadLocal<Integer>() {
@Override protected Integer initialValue() {
return nextId.getAndIncrement();
}
};
// Returns the current thread's unique ID, assigning it if necessary
public static int get() {
return threadId.get();
}
}
Each thread holds an implicit reference to its copy of a thread-local
variable as long as the thread is alive and the ThreadLocal
instance is accessible; after a thread goes away, all of its copies of
thread-local instances are subject to garbage collection (unless other
references to these copies exist).
| Modifier and Type | Class and Description |
|---|---|
| pack-priv static class | ThreadLocal.
An extension of ThreadLocal that obtains its initial value from
the specified |
| pack-priv static class | ThreadLocal.
ThreadLocalMap is a customized hash map suitable only for maintaining thread local values. |
| Modifier and Type | Field and Description |
|---|---|
| private static final ThreadLocal | |
| private static final int | HASH_INCREMENT
The difference between successively generated hash codes - turns implicit sequential thread-local IDs into near-optimally spread multiplicative hash values for power-of-two-sized tables. |
| private static final AtomicInteger | nextHashCode
The next hash code to be given out. |
| private final int | threadLocalHashCode
ThreadLocals rely on per-thread linear-probe hash maps attached to each thread (Thread.threadLocals and inheritableThreadLocals). |
| private static final boolean |
| Access | Constructor and Description |
|---|---|
| public |
| Modifier and Type | Method and Description |
|---|---|
| pack-priv T | childValue(T parentValue)
Method childValue is visibly defined in subclass InheritableThreadLocal, but is internally defined here for the sake of providing createInheritedMap factory method without needing to subclass the map class in InheritableThreadLocal. |
| pack-priv static ThreadLocal. | Returns: a map containing the parent's inheritable bindingsthe map associated with parent thread parentMapFactory method to create map of inherited thread locals. |
| pack-priv void | |
| public T | Returns: the current thread's value of this thread-localReturns the value in the current thread's copy of this thread-local variable. |
| private T | |
| pack-priv T | getCarrierThreadLocal()
Returns the value in the current carrier thread's copy of this thread-local variable. |
| pack-priv ThreadLocal. | |
| protected T | Returns: the initial value for this thread-localReturns the current thread's "initial value" for this thread-local variable. |
| private static int | |
| private void | |
| public void | |
| private void | |
| pack-priv void | |
| public void | set(T
the value to be stored in the current thread's copy of
this thread-local. value)Sets the current thread's copy of this thread-local variable to the specified value. |
| private void | |
| pack-priv void | |
| private T | |
| private static boolean | traceVirtualThreadLocals()
Reads the value of the jdk.traceVirtualThreadLocals property to determine if a stack trace should be printed when a virtual thread sets a thread local. |
| public static < the type of the thread local's value S> ThreadLocal | Returns: a new thread local variablethe supplier to be used to determine the initial value supplier)Creates a thread local variable. |
| DUMPING_STACK | back to summary |
|---|---|
| private static final ThreadLocal<Boolean> DUMPING_STACK | |
| HASH_INCREMENT | back to summary |
|---|---|
| private static final int HASH_INCREMENT The difference between successively generated hash codes - turns implicit sequential thread-local IDs into near-optimally spread multiplicative hash values for power-of-two-sized tables. | |
| nextHashCode | back to summary |
|---|---|
| private static final AtomicInteger nextHashCode The next hash code to be given out. Updated atomically. Starts at zero. | |
| threadLocalHashCode | back to summary |
|---|---|
| private final int threadLocalHashCode ThreadLocals rely on per-thread linear-probe hash maps attached to each thread (Thread.threadLocals and inheritableThreadLocals). The ThreadLocal objects act as keys, searched via threadLocalHashCode. This is a custom hash code (useful only within ThreadLocalMaps) that eliminates collisions in the common case where consecutively constructed ThreadLocals are used by the same threads, while remaining well-behaved in less common cases. | |
| TRACE_VTHREAD_LOCALS | back to summary |
|---|---|
| private static final boolean TRACE_VTHREAD_LOCALS | |
| ThreadLocal | back to summary |
|---|---|
| public ThreadLocal() Creates a thread local variable. | |
| childValue | back to summary |
|---|---|
| pack-priv T childValue(T parentValue) Method childValue is visibly defined in subclass InheritableThreadLocal, but is internally defined here for the sake of providing createInheritedMap factory method without needing to subclass the map class in InheritableThreadLocal. This technique is preferable to the alternative of embedding instanceof tests in methods. | |
| createInheritedMap | back to summary |
|---|---|
| pack-priv static ThreadLocal. Factory method to create map of inherited thread locals. Designed to be called only from Thread constructor.
| |
| createMap | back to summary |
|---|---|
| pack-priv void createMap(Thread t, T firstValue) Create the map associated with a ThreadLocal. Overridden in InheritableThreadLocal.
| |
| get | back to summary |
|---|---|
| public T get() Returns the value in the current thread's copy of this
thread-local variable. If the variable has no value for the
current thread, it is first initialized to the value returned
by an invocation of the
| |
| get | back to summary |
|---|---|
| private T get(Thread t) | |
| getCarrierThreadLocal | back to summary |
|---|---|
| pack-priv T getCarrierThreadLocal() Returns the value in the current carrier thread's copy of this thread-local variable. | |
| getMap | back to summary |
|---|---|
| pack-priv ThreadLocal. Get the map associated with a ThreadLocal. Overridden in InheritableThreadLocal.
| |
| initialValue | back to summary |
|---|---|
| protected T initialValue() Returns the current thread's "initial value" for this
thread-local variable. This method will be invoked the first
time a thread accesses the variable with the Implementation Specification This implementation simply returns
| |
| nextHashCode | back to summary |
|---|---|
| private static int nextHashCode() Returns the next hash code. | |
| printStackTrace | back to summary |
|---|---|
| private void printStackTrace() Print the stack trace of the current thread, skipping the printStackTrace frame. A thread local is used to detect reentrancy as the printing may itself use thread locals. | |
| remove | back to summary |
|---|---|
| public void remove() Removes the current thread's value for this thread-local
variable. If this thread-local variable is subsequently
read by the current thread, its value will be
reinitialized by invoking its
| |
| remove | back to summary |
|---|---|
| private void remove(Thread t) | |
| removeCarrierThreadLocal | back to summary |
|---|---|
| pack-priv void removeCarrierThreadLocal() | |
| set | back to summary |
|---|---|
| public void set(T value) Sets the current thread's copy of this thread-local variable
to the specified value. Most subclasses will have no need to
override this method, relying solely on the
| |
| set | back to summary |
|---|---|
| private void set(Thread t, T value) | |
| setCarrierThreadLocal | back to summary |
|---|---|
| pack-priv void setCarrierThreadLocal(T value) | |
| setInitialValue | back to summary |
|---|---|
| private T setInitialValue(Thread t) Variant of set() to establish initialValue. Used instead of set() in case user has overridden the set() method.
| |
| traceVirtualThreadLocals | back to summary |
|---|---|
| private static boolean traceVirtualThreadLocals() Reads the value of the jdk.traceVirtualThreadLocals property to determine if a stack trace should be printed when a virtual thread sets a thread local. | |
| withInitial | back to summary |
|---|---|
| public static <S> ThreadLocal Creates a thread local variable. The initial value of the variable is
determined by invoking the
| |
Supplier.
| Access | Constructor and Description |
|---|---|
| pack-priv |
| Modifier and Type | Method and Description |
|---|---|
| protected T | initialValue()
Overrides java. Returns the current thread's "initial value" for this thread-local variable. |
| supplier | back to summary |
|---|---|
| private final Supplier<? extends T> supplier | |
| SuppliedThreadLocal | back to summary |
|---|---|
| pack-priv SuppliedThreadLocal(Supplier<? extends T> supplier) | |
| initialValue | back to summary |
|---|---|
| protected T initialValue() Overrides java. Doc from java. Returns the current thread's "initial value" for this
thread-local variable. This method will be invoked the first
time a thread accesses the variable with the
| |
| Modifier and Type | Class and Description |
|---|---|
| pack-priv static class | ThreadLocal.
The entries in this hash map extend WeakReference, using its main ref field as the key (which is always a ThreadLocal object). |
| Modifier and Type | Field and Description |
|---|---|
| private static final int | INITIAL_CAPACITY
The initial capacity -- MUST be a power of two. |
| private int | size
The number of entries in the table. |
| private ThreadLocal. | table
The table, resized as necessary. |
| private int | threshold
The next size value at which to resize. |
| Access | Constructor and Description |
|---|---|
| private | |
| pack-priv | ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue)
Construct a new map initially containing (firstKey, firstValue). |
| private | ThreadLocalMap(ThreadLocal.
the map associated with parent thread. parentMapConstruct a new map including all Inheritable ThreadLocals from given parent map. |
| Modifier and Type | Method and Description |
|---|---|
| private boolean | Returns: true if any stale entries have been removed.a position known NOT to hold a stale entry. The
scan starts at the element after i. i, int scan control: n)log2(n) cells are scanned,
unless a stale entry is found, in which case
log2(table.length)-1 additional cells are scanned.
When called from insertions, this parameter is the number
of elements, but when from replaceStaleEntry, it is the
table length. (Note: all this could be changed to be either
more or less aggressive by weighting n instead of just
using straight log n. But this version is simple, fast, and
seems to work well.)Heuristically scan some cells looking for stale entries. |
| private void | |
| private int | Returns: the index of the next null slot after staleSlot (all between staleSlot and this slot will have been checked for expunging).index of slot known to have null key staleSlot)Expunge a stale entry by rehashing any possibly colliding entries lying between staleSlot and the next null slot. |
| private ThreadLocal. | Returns: the entry associated with key, or null if no suchthe thread local object key)Get the entry associated with key. |
| private ThreadLocal. | Returns: the entry associated with key, or null if no suchthe thread local object key, int the table index for key's hash code i, ThreadLocal.the entry at table[i] eVersion of getEntry method for use when key is not found in its direct hash slot. |
| private static int | |
| private static int | |
| private void | |
| private void | |
| private void | replaceStaleEntry(ThreadLocal<?>
the key key, Object the value to be associated with key value, int index of the first stale entry encountered while
searching for key. staleSlot)Replace a stale entry encountered during a set operation with an entry for the specified key. |
| private void | |
| private void | set(ThreadLocal<?>
the thread local object key, Object the value to be set value)Set the value associated with key. |
| private void | |
| pack-priv int |
| INITIAL_CAPACITY | back to summary |
|---|---|
| private static final int INITIAL_CAPACITY The initial capacity -- MUST be a power of two. | |
| size | back to summary |
|---|---|
| private int size The number of entries in the table. | |
| table | back to summary |
|---|---|
| private ThreadLocal. The table, resized as necessary. table.length MUST always be a power of two. | |
| threshold | back to summary |
|---|---|
| private int threshold The next size value at which to resize. | |
| ThreadLocalMap | back to summary |
|---|---|
| private ThreadLocalMap() Construct a new map without a table. | |
| ThreadLocalMap | back to summary |
|---|---|
| pack-priv ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) Construct a new map initially containing (firstKey, firstValue). ThreadLocalMaps are constructed lazily, so we only create one when we have at least one entry to put in it. | |
| ThreadLocalMap | back to summary |
|---|---|
| private ThreadLocalMap(ThreadLocal. Construct a new map including all Inheritable ThreadLocals from given parent map. Called only by createInheritedMap.
| |
| cleanSomeSlots | back to summary |
|---|---|
| private boolean cleanSomeSlots(int i, int n) Heuristically scan some cells looking for stale entries. This is invoked when either a new element is added, or another stale one has been expunged. It performs a logarithmic number of scans, as a balance between no scanning (fast but retains garbage) and a number of scans proportional to number of elements, that would find all garbage but would cause some insertions to take O(n) time.
| |
| expungeStaleEntries | back to summary |
|---|---|
| private void expungeStaleEntries() Expunge all stale entries in the table. | |
| expungeStaleEntry | back to summary |
|---|---|
| private int expungeStaleEntry(int staleSlot) Expunge a stale entry by rehashing any possibly colliding entries lying between staleSlot and the next null slot. This also expunges any other stale entries encountered before the trailing null. See Knuth, Section 6.4
| |
| getEntry | back to summary |
|---|---|
| private ThreadLocal. Get the entry associated with key. This method itself handles only the fast path: a direct hit of existing key. It otherwise relays to getEntryAfterMiss. This is designed to maximize performance for direct hits, in part by making this method readily inlinable.
| |
| getEntryAfterMiss | back to summary |
|---|---|
| private ThreadLocal. Version of getEntry method for use when key is not found in its direct hash slot.
| |
| nextIndex | back to summary |
|---|---|
| private static int nextIndex(int i, int len) Increment i modulo len. | |
| prevIndex | back to summary |
|---|---|
| private static int prevIndex(int i, int len) Decrement i modulo len. | |
| rehash | back to summary |
|---|---|
| private void rehash() Re-pack and/or re-size the table. First scan the entire table removing stale entries. If this doesn't sufficiently shrink the size of the table, double the table size. | |
| remove | back to summary |
|---|---|
| private void remove(ThreadLocal<?> key) Remove the entry for key. | |
| replaceStaleEntry | back to summary |
|---|---|
| private void replaceStaleEntry(ThreadLocal<?> key, Object value, int staleSlot) Replace a stale entry encountered during a set operation with an entry for the specified key. The value passed in the value parameter is stored in the entry, whether or not an entry already exists for the specified key. As a side effect, this method expunges all stale entries in the "run" containing the stale entry. (A run is a sequence of entries between two null slots.)
| |
| resize | back to summary |
|---|---|
| private void resize() Double the capacity of the table. | |
| set | back to summary |
|---|---|
| private void set(ThreadLocal<?> key, Object value) Set the value associated with key.
| |
| setThreshold | back to summary |
|---|---|
| private void setThreshold(int len) Set the resize threshold to maintain at worst a 2/3 load factor. | |
| size | back to summary |
|---|---|
| pack-priv int size() Returns the number of elements in the map. | |
| Modifier and Type | Field and Description |
|---|---|
| pack-priv Object | value
The value associated with this ThreadLocal. |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| value | back to summary |
|---|---|
| pack-priv Object value The value associated with this ThreadLocal. | |
| Entry | back to summary |
|---|---|
| pack-priv Entry(ThreadLocal<?> k, Object v) | |