Class ThreadLocalHolder<T>

java.lang.Object
org.dellroad.stuff.java.ThreadLocalHolder<T>
Type Parameters:
T - the type of the thread local variable

public class ThreadLocalHolder<T> extends Object
Manages a thread local whose lifetime matches the duration of some method call.

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 Details

    • ThreadLocalHolder

      public ThreadLocalHolder()
      Conveninece constructor.

      Equivalent to:

      new ThreadLocalHolder<T>(new ThreadLocal<T>())
    • ThreadLocalHolder

      public ThreadLocalHolder(ThreadLocal<T> threadLocal)
      Primary constructor.
      Parameters:
      threadLocal - the thread local to use
      Throws:
      IllegalArgumentException - if threadLocal is null
  • Method Details

    • invoke

      public void invoke(T value, Runnable action)
      Invoke the given action while making the given thread local variable available via get() and require().

      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 if value is the exact same Java object (using object equality, not equals()), execution proceeds normally, otherwise an exception is thrown.

      Parameters:
      value - value for the thread local variable
      action - action to invoke
      Throws:
      IllegalArgumentException - if either action or value is null
      IllegalStateException - if there is already a thread local variable previous associated with the current thread and value != previous
    • invoke

      public <R> R invoke(T value, Supplier<R> action)
      Invoke the given action while making the given thread local variable available via get() and require().

      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 if value is the exact same Java object (using object equality, not equals()), execution proceeds normally, otherwise an exception is thrown.

      Type Parameters:
      R - action return type
      Parameters:
      value - value for the thread local variable
      action - action to invoke
      Returns:
      result of invoking action
      Throws:
      IllegalArgumentException - if either action or value is null
      IllegalStateException - if there is already a thread local variable previous associated with the current thread and value != previous
    • get

      public T 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

      public T 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 of ThreadLocalHolder.invoke()
    • destroy

      protected void destroy(T value)
      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