Class ThreadLocalHolder<T>
- Type Parameters:
T
- the type of the thread local variable
This class is useful for this common pattern:
- A thread local variable is instantiated by some initial method call and has an intended lifetime matching the duration of that method call;
- The thread local variable is accessible from some other nested method calls in the same thread, as long as the initial method call is still executing;
- The thread local variable is removed (and optionally cleaned up) when the initial method call exits, whether successfully or not.
Example:
public class FooContext {
private static final ThreadLocalHolder<FooContext> CURRENT = new ThreadLocalHolder<>();
/**
* Make this instance the current instance while performing the given activity.
*
* @throws IllegalArgumentException if {@code action} is null
* @throws IllegalStateException if there is already another, different current instance
*/
public void doWhileCurrent(Runnable action) {
CURRENT_ACTIVITY.invoke(this, action);
}
/**
* Get the current {@link FooContext}.
*
* @throws IllegalStateException if the current thread is not running within an invocation of {@link #doWhileCurrent}
*/
public static FooContext getCurrent() {
return CURRENT.require();
}
}
-
Constructor Summary
ConstructorDescriptionConveninece constructor.ThreadLocalHolder
(ThreadLocal<T> threadLocal) Primary constructor. -
Method Summary
-
Constructor Details
-
ThreadLocalHolder
public ThreadLocalHolder()Conveninece constructor.Equivalent to:
new ThreadLocalHolder<T>(new ThreadLocal<T>())
-
ThreadLocalHolder
Primary constructor.- Parameters:
threadLocal
- the thread local to use- Throws:
IllegalArgumentException
- ifthreadLocal
is null
-
-
Method Details
-
invoke
Invoke the given action while making the given thread local variable available viaget()
andrequire()
.If there is already a thread local variable set for the current thread (i.e., we are already executing within an invocation of
ThreadLocalHolder.invoke()
), then ifvalue
is the exact same Java object (using object equality, notequals()
), execution proceeds normally, otherwise an exception is thrown.- Parameters:
value
- value for the thread local variableaction
- action to invoke- Throws:
IllegalArgumentException
- if eitheraction
orvalue
is nullIllegalStateException
- if there is already a thread local variableprevious
associated with the current thread andvalue != previous
-
invoke
Invoke the given action while making the given thread local variable available viaget()
andrequire()
.If there is already a thread local variable set for the current thread (i.e., we are already executing within an invocation of
ThreadLocalHolder.invoke()
), then ifvalue
is the exact same Java object (using object equality, notequals()
), execution proceeds normally, otherwise an exception is thrown.- Type Parameters:
R
- action return type- Parameters:
value
- value for the thread local variableaction
- action to invoke- Returns:
- result of invoking
action
- Throws:
IllegalArgumentException
- if eitheraction
orvalue
is nullIllegalStateException
- if there is already a thread local variableprevious
associated with the current thread andvalue != previous
-
get
Get the thread local value associated with the current thread, if any.- Returns:
- the current thread local variable value, or null if not executing
within an invocation of
ThreadLocalHolder.invoke()
-
require
Get the thread local value associated with the current thread; there must be one.- Returns:
- the current thread local variable value, never null
- Throws:
IllegalStateException
- if the current thread is not running within an invocation ofThreadLocalHolder.invoke()
-
destroy
Clean up the thread local value when no longer needed.The implementation in
ThreadLocalHolder
does nothing. Subclasses may override if necessary.- Parameters:
value
- previously used thread-local value
-