APIdia Launch Partner
Top Description Inners Fields Constructors Methods
java.lang

public Class ThreadLocal<T>

extends Object
Class Inheritance
Known Direct Subclasses
java.lang.ThreadLocal.SuppliedThreadLocal, java.util.concurrent.Exchanger.Participant, java.util.concurrent.locks.ReentrantReadWriteLock.Sync.ThreadLocalHoldCounter, jdk.internal.misc.CarrierThreadLocal, java.lang.InheritableThreadLocal
Type Parameters
<T>
the type of the thread local's value
Imports
java.lang.ref.WeakReference, java.util.Objects, java.util.concurrent.atomic.AtomicInteger, java.util.function.Supplier, java.util.stream.Collectors, jdk.internal.misc.CarrierThreadLocal, .TerminatingThreadLocal

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its 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).

Author
Josh Bloch and Doug Lea
Since
1.2

Nested and Inner Type Summary

Modifier and TypeClass and Description
pack-priv static class
ThreadLocal.SuppliedThreadLocal<T>

An extension of ThreadLocal that obtains its initial value from the specified Supplier.

pack-priv static class
ThreadLocal.ThreadLocalMap

ThreadLocalMap is a customized hash map suitable only for maintaining thread local values.

Field Summary

Modifier and TypeField and Description
private static final ThreadLocal<Boolean>
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

Constructor Summary

AccessConstructor and Description
public
ThreadLocal()

Creates a thread local variable.

Method Summary

Modifier and TypeMethod 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.ThreadLocalMap

Returns:

a map containing the parent's inheritable bindings
createInheritedMap
(ThreadLocal.ThreadLocalMap
the map associated with parent thread
parentMap
)

Factory method to create map of inherited thread locals.

pack-priv void
createMap(Thread
the current thread
t
,
T
value for the initial entry of the map
firstValue
)

Create the map associated with a ThreadLocal.

public T

Returns:

the current thread's value of this thread-local
get
()

Returns 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.ThreadLocalMap

Returns:

the map
getMap
(Thread
the current thread
t
)

Get the map associated with a ThreadLocal.

protected T

Returns:

the initial value for this thread-local
initialValue
()

Returns the current thread's "initial value" for this thread-local variable.

private static int
nextHashCode()

Returns the next hash code.

private void
printStackTrace()

Print the stack trace of the current thread, skipping the printStackTrace frame.

public void
remove()

Removes the current thread's value for this thread-local variable.

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
set(Thread t, T value)

pack-priv void
private T

Returns:

the initial value
setInitialValue
(Thread t)

Variant of set() to establish initialValue.

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<S>

Returns:

a new thread local variable
withInitial
(Supplier<? extends S>
the supplier to be used to determine the initial value
supplier
)

Creates a thread local variable.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

DUMPING_STACKback to summary
private static final ThreadLocal<Boolean> DUMPING_STACK
HASH_INCREMENTback 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.

nextHashCodeback to summary
private static final AtomicInteger nextHashCode

The next hash code to be given out. Updated atomically. Starts at zero.

threadLocalHashCodeback 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_LOCALSback to summary
private static final boolean TRACE_VTHREAD_LOCALS

Constructor Detail

ThreadLocalback to summary
public ThreadLocal()

Creates a thread local variable.

See Also
withInitial(java.util.function.Supplier)

Method Detail

childValueback 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.

createInheritedMapback to summary
pack-priv static ThreadLocal.ThreadLocalMap createInheritedMap(ThreadLocal.ThreadLocalMap parentMap)

Factory method to create map of inherited thread locals. Designed to be called only from Thread constructor.

Parameters
parentMap:ThreadLocal.ThreadLocalMap

the map associated with parent thread

Returns:ThreadLocal.ThreadLocalMap

a map containing the parent's inheritable bindings

createMapback to summary
pack-priv void createMap(Thread t, T firstValue)

Create the map associated with a ThreadLocal. Overridden in InheritableThreadLocal.

Parameters
t:Thread

the current thread

firstValue:T

value for the initial entry of the map

getback 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 initialValue method.

Returns:T

the current thread's value of this thread-local

getback to summary
private T get(Thread t)
getCarrierThreadLocalback to summary
pack-priv T getCarrierThreadLocal()

Returns the value in the current carrier thread's copy of this thread-local variable.

getMapback to summary
pack-priv ThreadLocal.ThreadLocalMap getMap(Thread t)

Get the map associated with a ThreadLocal. Overridden in InheritableThreadLocal.

Parameters
t:Thread

the current thread

Returns:ThreadLocal.ThreadLocalMap

the map

initialValueback 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 get method, unless the thread previously invoked the set method, in which case the initialValue method will not be invoked for the thread. Normally, this method is invoked at most once per thread, but it may be invoked again in case of subsequent invocations of remove followed by get.

Implementation Specification

This implementation simply returns null; if the programmer desires thread-local variables to have an initial value other than null, then either ThreadLocal can be subclassed and this method overridden or the method ThreadLocal#withInitial(Supplier) can be used to construct a ThreadLocal.

Returns:T

the initial value for this thread-local

See Also
withInitial(java.util.function.Supplier)
nextHashCodeback to summary
private static int nextHashCode()

Returns the next hash code.

printStackTraceback 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.

removeback 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 initialValue method, unless its value is set by the current thread in the interim. This may result in multiple invocations of the initialValue method in the current thread.

Since
1.5
removeback to summary
private void remove(Thread t)
removeCarrierThreadLocalback to summary
pack-priv void removeCarrierThreadLocal()
setback 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 initialValue method to set the values of thread-locals.

Parameters
value:T

the value to be stored in the current thread's copy of this thread-local.

setback to summary
private void set(Thread t, T value)
setCarrierThreadLocalback to summary
pack-priv void setCarrierThreadLocal(T value)
setInitialValueback 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.

Returns:T

the initial value

traceVirtualThreadLocalsback 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.

withInitialback to summary
public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier)

Creates a thread local variable. The initial value of the variable is determined by invoking the get method on the Supplier.

Parameters
<S>
the type of the thread local's value
supplier:Supplier<? extends S>

the supplier to be used to determine the initial value

Returns:ThreadLocal<S>

a new thread local variable

Exceptions
NullPointerException:
if the specified supplier is null
Since
1.8
java.lang back to summary

pack-priv final Class ThreadLocal.SuppliedThreadLocal<T>

extends ThreadLocal<T>
Class Inheritance

An extension of ThreadLocal that obtains its initial value from the specified Supplier.

Field Summary

Modifier and TypeField and Description
private final Supplier<? extends T>

Constructor Summary

AccessConstructor and Description
pack-priv
SuppliedThreadLocal(Supplier<? extends T> supplier)

Method Summary

Modifier and TypeMethod and Description
protected T
initialValue()

Overrides java.lang.ThreadLocal.initialValue.

Returns the current thread's "initial value" for this thread-local variable.

Inherited from java.lang.ThreadLocal:
childValuecreateInheritedMapcreateMapgetgetCarrierThreadLocalgetMapremoveremoveCarrierThreadLocalsetsetCarrierThreadLocalwithInitial

Field Detail

supplierback to summary
private final Supplier<? extends T> supplier

Constructor Detail

SuppliedThreadLocalback to summary
pack-priv SuppliedThreadLocal(Supplier<? extends T> supplier)

Method Detail

initialValueback to summary
protected T initialValue()

Overrides java.lang.ThreadLocal.initialValue.

Doc from java.lang.ThreadLocal.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 get method, unless the thread previously invoked the set method, in which case the initialValue method will not be invoked for the thread. Normally, this method is invoked at most once per thread, but it may be invoked again in case of subsequent invocations of remove followed by get.

Annotations
@Override
java.lang back to summary

pack-priv Class ThreadLocal.ThreadLocalMap

extends Object
Class Inheritance

ThreadLocalMap is a customized hash map suitable only for maintaining thread local values. No operations are exported outside of the ThreadLocal class. The class is package private to allow declaration of fields in class Thread. To help deal with very large and long-lived usages, the hash table entries use WeakReferences for keys. However, since reference queues are not used, stale entries are guaranteed to be removed only when the table starts running out of space.

Nested and Inner Type Summary

Modifier and TypeClass and Description
pack-priv static class
ThreadLocal.ThreadLocalMap.Entry

The entries in this hash map extend WeakReference, using its main ref field as the key (which is always a ThreadLocal object).

Field Summary

Modifier and TypeField 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.ThreadLocalMap.Entry[]
table

The table, resized as necessary.

private int
threshold

The next size value at which to resize.

Constructor Summary

AccessConstructor and Description
private
ThreadLocalMap()

Construct a new map without a table.

pack-priv
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue)

Construct a new map initially containing (firstKey, firstValue).

private
ThreadLocalMap(ThreadLocal.ThreadLocalMap
the map associated with parent thread.
parentMap
)

Construct a new map including all Inheritable ThreadLocals from given parent map.

Method Summary

Modifier and TypeMethod and Description
private boolean

Returns:

true if any stale entries have been removed.
cleanSomeSlots
(int
a position known NOT to hold a stale entry. The scan starts at the element after i.
i
,
int
scan control: 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.)
n
)

Heuristically scan some cells looking for stale entries.

private void
expungeStaleEntries()

Expunge all stale entries in the table.

private int

Returns:

the index of the next null slot after staleSlot (all between staleSlot and this slot will have been checked for expunging).
expungeStaleEntry
(int
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.ThreadLocalMap.Entry

Returns:

the entry associated with key, or null if no such
getEntry
(ThreadLocal<?>
the thread local object
key
)

Get the entry associated with key.

private ThreadLocal.ThreadLocalMap.Entry

Returns:

the entry associated with key, or null if no such
getEntryAfterMiss
(ThreadLocal<?>
the thread local object
key
,
int
the table index for key's hash code
i
,
ThreadLocal.ThreadLocalMap.Entry
the entry at table[i]
e
)

Version of getEntry method for use when key is not found in its direct hash slot.

private static int
nextIndex(int i, int len)

Increment i modulo len.

private static int
prevIndex(int i, int len)

Decrement i modulo len.

private void
rehash()

Re-pack and/or re-size the table.

private void
remove(ThreadLocal<?> key)

Remove the entry for key.

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
resize()

Double the capacity of the table.

private void
set(ThreadLocal<?>
the thread local object
key
,
Object
the value to be set
value
)

Set the value associated with key.

private void
setThreshold(int len)

Set the resize threshold to maintain at worst a 2/3 load factor.

pack-priv int
size()

Returns the number of elements in the map.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

INITIAL_CAPACITYback to summary
private static final int INITIAL_CAPACITY

The initial capacity -- MUST be a power of two.

sizeback to summary
private int size

The number of entries in the table.

tableback to summary
private ThreadLocal.ThreadLocalMap.Entry[] table

The table, resized as necessary. table.length MUST always be a power of two.

thresholdback to summary
private int threshold

The next size value at which to resize.

Constructor Detail

ThreadLocalMapback to summary
private ThreadLocalMap()

Construct a new map without a table.

ThreadLocalMapback 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.

ThreadLocalMapback to summary
private ThreadLocalMap(ThreadLocal.ThreadLocalMap parentMap)

Construct a new map including all Inheritable ThreadLocals from given parent map. Called only by createInheritedMap.

Parameters
parentMap:ThreadLocal.ThreadLocalMap

the map associated with parent thread.

Method Detail

cleanSomeSlotsback 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.

Parameters
i:int

a position known NOT to hold a stale entry. The scan starts at the element after i.

n:int

scan control: 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.)

Returns:boolean

true if any stale entries have been removed.

expungeStaleEntriesback to summary
private void expungeStaleEntries()

Expunge all stale entries in the table.

expungeStaleEntryback 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

Parameters
staleSlot:int

index of slot known to have null key

Returns:int

the index of the next null slot after staleSlot (all between staleSlot and this slot will have been checked for expunging).

getEntryback to summary
private ThreadLocal.ThreadLocalMap.Entry getEntry(ThreadLocal<?> key)

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.

Parameters
key:ThreadLocal<?>

the thread local object

Returns:ThreadLocal.ThreadLocalMap.Entry

the entry associated with key, or null if no such

getEntryAfterMissback to summary
private ThreadLocal.ThreadLocalMap.Entry getEntryAfterMiss(ThreadLocal<?> key, int i, ThreadLocal.ThreadLocalMap.Entry e)

Version of getEntry method for use when key is not found in its direct hash slot.

Parameters
key:ThreadLocal<?>

the thread local object

i:int

the table index for key's hash code

e:ThreadLocal.ThreadLocalMap.Entry

the entry at table[i]

Returns:ThreadLocal.ThreadLocalMap.Entry

the entry associated with key, or null if no such

nextIndexback to summary
private static int nextIndex(int i, int len)

Increment i modulo len.

prevIndexback to summary
private static int prevIndex(int i, int len)

Decrement i modulo len.

rehashback 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.

removeback to summary
private void remove(ThreadLocal<?> key)

Remove the entry for key.

replaceStaleEntryback 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.)

Parameters
key:ThreadLocal<?>

the key

value:Object

the value to be associated with key

staleSlot:int

index of the first stale entry encountered while searching for key.

resizeback to summary
private void resize()

Double the capacity of the table.

setback to summary
private void set(ThreadLocal<?> key, Object value)

Set the value associated with key.

Parameters
key:ThreadLocal<?>

the thread local object

value:Object

the value to be set

setThresholdback to summary
private void setThreshold(int len)

Set the resize threshold to maintain at worst a 2/3 load factor.

sizeback to summary
pack-priv int size()

Returns the number of elements in the map.

java.lang back to summary

pack-priv Class ThreadLocal.ThreadLocalMap.Entry

extends WeakReference<ThreadLocal<?>>
Class Inheritance

The entries in this hash map extend WeakReference, using its main ref field as the key (which is always a ThreadLocal object). Note that null keys (i.e. entry.get() == null) mean that the key is no longer referenced, so the entry can be expunged from table. Such entries are referred to as "stale entries" in the code that follows.

Field Summary

Modifier and TypeField and Description
pack-priv Object
value

The value associated with this ThreadLocal.

Constructor Summary

AccessConstructor and Description
pack-priv

Field Detail

valueback to summary
pack-priv Object value

The value associated with this ThreadLocal.

Constructor Detail

Entryback to summary
pack-priv Entry(ThreadLocal<?> k, Object v)