src/share/classes/java/lang/ThreadLocal.java

Print this page
rev 6191 : [mq]: threadlocal


   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang;
  27 import java.lang.ref.*;

  28 import java.util.concurrent.atomic.AtomicInteger;

  29 
  30 /**
  31  * This class provides thread-local variables.  These variables differ from
  32  * their normal counterparts in that each thread that accesses one (via its
  33  * <tt>get</tt> or <tt>set</tt> method) has its own, independently initialized
  34  * copy of the variable.  <tt>ThreadLocal</tt> instances are typically private
  35  * static fields in classes that wish to associate state with a thread (e.g.,
  36  * a user ID or Transaction ID).
  37  *
  38  * <p>For example, the class below generates unique identifiers local to each
  39  * thread.
  40  * A thread's id is assigned the first time it invokes <tt>ThreadId.get()</tt>
  41  * and remains unchanged on subsequent calls.
  42  * <pre>
  43  * import java.util.concurrent.atomic.AtomicInteger;
  44  *
  45  * public class ThreadId {
  46  *     // Atomic integer containing the next thread ID to be assigned
  47  *     private static final AtomicInteger nextId = new AtomicInteger(0);
  48  *
  49  *     // Thread local variable containing each thread's ID
  50  *     private static final ThreadLocal&lt;Integer&gt; threadId =
  51  *         new ThreadLocal&lt;Integer&gt;() {
  52  *             &#64;Override protected Integer initialValue() {
  53  *                 return nextId.getAndIncrement();
  54  *         }
  55  *     };
  56  *
  57  *     // Returns the current thread's unique ID, assigning it if necessary
  58  *     public static int get() {
  59  *         return threadId.get();
  60  *     }
  61  * }
  62  * </pre>
  63  * <p>Each thread holds an implicit reference to its copy of a thread-local
  64  * variable as long as the thread is alive and the <tt>ThreadLocal</tt>
  65  * instance is accessible; after a thread goes away, all of its copies of
  66  * thread-local instances are subject to garbage collection (unless other
  67  * references to these copies exist).
  68  *
  69  * @author  Josh Bloch and Doug Lea
  70  * @since   1.2
  71  */
  72 public class ThreadLocal<T> {
  73     /**
  74      * ThreadLocals rely on per-thread linear-probe hash maps attached
  75      * to each thread (Thread.threadLocals and
  76      * inheritableThreadLocals).  The ThreadLocal objects act as keys,
  77      * searched via threadLocalHashCode.  This is a custom hash code
  78      * (useful only within ThreadLocalMaps) that eliminates collisions
  79      * in the common case where consecutively constructed ThreadLocals
  80      * are used by the same threads, while remaining well-behaved in
  81      * less common cases.
  82      */
  83     private final int threadLocalHashCode = nextHashCode();
  84 


  91 
  92     /**
  93      * The difference between successively generated hash codes - turns
  94      * implicit sequential thread-local IDs into near-optimally spread
  95      * multiplicative hash values for power-of-two-sized tables.
  96      */
  97     private static final int HASH_INCREMENT = 0x61c88647;
  98 
  99     /**
 100      * Returns the next hash code.
 101      */
 102     private static int nextHashCode() {
 103         return nextHashCode.getAndAdd(HASH_INCREMENT);
 104     }
 105 
 106     /**
 107      * Returns the current thread's "initial value" for this
 108      * thread-local variable.  This method will be invoked the first
 109      * time a thread accesses the variable with the {@link #get}
 110      * method, unless the thread previously invoked the {@link #set}
 111      * method, in which case the <tt>initialValue</tt> method will not
 112      * be invoked for the thread.  Normally, this method is invoked at
 113      * most once per thread, but it may be invoked again in case of
 114      * subsequent invocations of {@link #remove} followed by {@link #get}.
 115      *
 116      * <p>This implementation simply returns <tt>null</tt>; if the
 117      * programmer desires thread-local variables to have an initial
 118      * value other than <tt>null</tt>, <tt>ThreadLocal</tt> must be
 119      * subclassed, and this method overridden.  Typically, an
 120      * anonymous inner class will be used.
 121      *
 122      * @return the initial value for this thread-local
 123      */
 124     protected T initialValue() {
 125         return null;
 126     }
 127 
 128     /**












 129      * Creates a thread local variable.

 130      */
 131     public ThreadLocal() {
 132     }
 133 
 134     /**
 135      * Returns the value in the current thread's copy of this
 136      * thread-local variable.  If the variable has no value for the
 137      * current thread, it is first initialized to the value returned
 138      * by an invocation of the {@link #initialValue} method.
 139      *
 140      * @return the current thread's value of this thread-local
 141      */
 142     public T get() {
 143         Thread t = Thread.currentThread();
 144         ThreadLocalMap map = getMap(t);
 145         if (map != null) {
 146             ThreadLocalMap.Entry e = map.getEntry(this);
 147             if (e != null) {
 148                 @SuppressWarnings("unchecked")
 149                 T result = (T)e.value;


 178      *
 179      * @param value the value to be stored in the current thread's copy of
 180      *        this thread-local.
 181      */
 182     public void set(T value) {
 183         Thread t = Thread.currentThread();
 184         ThreadLocalMap map = getMap(t);
 185         if (map != null)
 186             map.set(this, value);
 187         else
 188             createMap(t, value);
 189     }
 190 
 191     /**
 192      * Removes the current thread's value for this thread-local
 193      * variable.  If this thread-local variable is subsequently
 194      * {@linkplain #get read} by the current thread, its value will be
 195      * reinitialized by invoking its {@link #initialValue} method,
 196      * unless its value is {@linkplain #set set} by the current thread
 197      * in the interim.  This may result in multiple invocations of the
 198      * <tt>initialValue</tt> method in the current thread.
 199      *
 200      * @since 1.5
 201      */
 202      public void remove() {
 203          ThreadLocalMap m = getMap(Thread.currentThread());
 204          if (m != null)
 205              m.remove(this);
 206      }
 207 
 208     /**
 209      * Get the map associated with a ThreadLocal. Overridden in
 210      * InheritableThreadLocal.
 211      *
 212      * @param  t the current thread
 213      * @return the map
 214      */
 215     ThreadLocalMap getMap(Thread t) {
 216         return t.threadLocals;
 217     }
 218 


 234      * @param  parentMap the map associated with parent thread
 235      * @return a map containing the parent's inheritable bindings
 236      */
 237     static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
 238         return new ThreadLocalMap(parentMap);
 239     }
 240 
 241     /**
 242      * Method childValue is visibly defined in subclass
 243      * InheritableThreadLocal, but is internally defined here for the
 244      * sake of providing createInheritedMap factory method without
 245      * needing to subclass the map class in InheritableThreadLocal.
 246      * This technique is preferable to the alternative of embedding
 247      * instanceof tests in methods.
 248      */
 249     T childValue(T parentValue) {
 250         throw new UnsupportedOperationException();
 251     }
 252 
 253     /**


















 254      * ThreadLocalMap is a customized hash map suitable only for
 255      * maintaining thread local values. No operations are exported
 256      * outside of the ThreadLocal class. The class is package private to
 257      * allow declaration of fields in class Thread.  To help deal with
 258      * very large and long-lived usages, the hash table entries use
 259      * WeakReferences for keys. However, since reference queues are not
 260      * used, stale entries are guaranteed to be removed only when
 261      * the table starts running out of space.
 262      */
 263     static class ThreadLocalMap {
 264 
 265         /**
 266          * The entries in this hash map extend WeakReference, using
 267          * its main ref field as the key (which is always a
 268          * ThreadLocal object).  Note that null keys (i.e. entry.get()
 269          * == null) mean that the key is no longer referenced, so the
 270          * entry can be expunged from table.  Such entries are referred to
 271          * as "stale entries" in the code that follows.
 272          */
 273         static class Entry extends WeakReference<ThreadLocal<?>> {


 582                             h = nextIndex(h, len);
 583                         tab[h] = e;
 584                     }
 585                 }
 586             }
 587             return i;
 588         }
 589 
 590         /**
 591          * Heuristically scan some cells looking for stale entries.
 592          * This is invoked when either a new element is added, or
 593          * another stale one has been expunged. It performs a
 594          * logarithmic number of scans, as a balance between no
 595          * scanning (fast but retains garbage) and a number of scans
 596          * proportional to number of elements, that would find all
 597          * garbage but would cause some insertions to take O(n) time.
 598          *
 599          * @param i a position known NOT to hold a stale entry. The
 600          * scan starts at the element after i.
 601          *
 602          * @param n scan control: <tt>log2(n)</tt> cells are scanned,
 603          * unless a stale entry is found, in which case
 604          * <tt>log2(table.length)-1</tt> additional cells are scanned.
 605          * When called from insertions, this parameter is the number
 606          * of elements, but when from replaceStaleEntry, it is the
 607          * table length. (Note: all this could be changed to be either
 608          * more or less aggressive by weighting n instead of just
 609          * using straight log n. But this version is simple, fast, and
 610          * seems to work well.)
 611          *
 612          * @return true if any stale entries have been removed.
 613          */
 614         private boolean cleanSomeSlots(int i, int n) {
 615             boolean removed = false;
 616             Entry[] tab = table;
 617             int len = tab.length;
 618             do {
 619                 i = nextIndex(i, len);
 620                 Entry e = tab[i];
 621                 if (e != null && e.get() == null) {
 622                     n = len;
 623                     removed = true;
 624                     i = expungeStaleEntry(i);




   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang;
  27 import java.lang.ref.*;
  28 import java.util.Objects;
  29 import java.util.concurrent.atomic.AtomicInteger;
  30 import java.util.function.Supplier;
  31 
  32 /**
  33  * This class provides thread-local variables.  These variables differ from
  34  * their normal counterparts in that each thread that accesses one (via its
  35  * {@code get} or {@code set} method) has its own, independently initialized
  36  * copy of the variable.  {@code ThreadLocal} instances are typically private
  37  * static fields in classes that wish to associate state with a thread (e.g.,
  38  * a user ID or Transaction ID).
  39  *
  40  * <p>For example, the class below generates unique identifiers local to each
  41  * thread.
  42  * A thread's id is assigned the first time it invokes {@code ThreadId.get()}
  43  * and remains unchanged on subsequent calls.
  44  * <pre>
  45  * import java.util.concurrent.atomic.AtomicInteger;
  46  *
  47  * public class ThreadId {
  48  *     // Atomic integer containing the next thread ID to be assigned
  49  *     private static final AtomicInteger nextId = new AtomicInteger(0);
  50  *
  51  *     // Thread local variable containing each thread's ID
  52  *     private static final ThreadLocal&lt;Integer&gt; threadId =
  53  *         new ThreadLocal&lt;Integer&gt;() {
  54  *             &#64;Override protected Integer initialValue() {
  55  *                 return nextId.getAndIncrement();
  56  *         }
  57  *     };
  58  *
  59  *     // Returns the current thread's unique ID, assigning it if necessary
  60  *     public static int get() {
  61  *         return threadId.get();
  62  *     }
  63  * }
  64  * </pre>
  65  * <p>Each thread holds an implicit reference to its copy of a thread-local
  66  * variable as long as the thread is alive and the {@code ThreadLocal}
  67  * instance is accessible; after a thread goes away, all of its copies of
  68  * thread-local instances are subject to garbage collection (unless other
  69  * references to these copies exist).
  70  *
  71  * @author  Josh Bloch and Doug Lea
  72  * @since   1.2
  73  */
  74 public class ThreadLocal<T> {
  75     /**
  76      * ThreadLocals rely on per-thread linear-probe hash maps attached
  77      * to each thread (Thread.threadLocals and
  78      * inheritableThreadLocals).  The ThreadLocal objects act as keys,
  79      * searched via threadLocalHashCode.  This is a custom hash code
  80      * (useful only within ThreadLocalMaps) that eliminates collisions
  81      * in the common case where consecutively constructed ThreadLocals
  82      * are used by the same threads, while remaining well-behaved in
  83      * less common cases.
  84      */
  85     private final int threadLocalHashCode = nextHashCode();
  86 


  93 
  94     /**
  95      * The difference between successively generated hash codes - turns
  96      * implicit sequential thread-local IDs into near-optimally spread
  97      * multiplicative hash values for power-of-two-sized tables.
  98      */
  99     private static final int HASH_INCREMENT = 0x61c88647;
 100 
 101     /**
 102      * Returns the next hash code.
 103      */
 104     private static int nextHashCode() {
 105         return nextHashCode.getAndAdd(HASH_INCREMENT);
 106     }
 107 
 108     /**
 109      * Returns the current thread's "initial value" for this
 110      * thread-local variable.  This method will be invoked the first
 111      * time a thread accesses the variable with the {@link #get}
 112      * method, unless the thread previously invoked the {@link #set}
 113      * method, in which case the {@code initialValue} method will not
 114      * be invoked for the thread.  Normally, this method is invoked at
 115      * most once per thread, but it may be invoked again in case of
 116      * subsequent invocations of {@link #remove} followed by {@link #get}.
 117      *
 118      * <p>This implementation simply returns {@code null}; if the
 119      * programmer desires thread-local variables to have an initial
 120      * value other than {@code null}, {@code ThreadLocal} must be
 121      * subclassed, and this method overridden.  Typically, an
 122      * anonymous inner class will be used.
 123      *
 124      * @return the initial value for this thread-local
 125      */
 126     protected T initialValue() {
 127         return null;
 128     }
 129 
 130     /**
 131      * Creates a thread local variable. The initial value of the variable is
 132      * determined by invoking the {@code get} method on the {@code Supplier}.
 133      *
 134      * @param supplier the supplier to be used to determine the initial value
 135      * @return a new thread local variable
 136      * @since 1.8
 137      */
 138     public static <T> ThreadLocal<T> withInitial(Supplier<? extends T> supplier) {
 139         return new SuppliedThreadLocal<>(supplier);
 140     }
 141 
 142     /**
 143      * Creates a thread local variable.
 144      * @see #withInitial(java.util.function.Supplier)
 145      */
 146     public ThreadLocal() {
 147     }
 148 
 149     /**
 150      * Returns the value in the current thread's copy of this
 151      * thread-local variable.  If the variable has no value for the
 152      * current thread, it is first initialized to the value returned
 153      * by an invocation of the {@link #initialValue} method.
 154      *
 155      * @return the current thread's value of this thread-local
 156      */
 157     public T get() {
 158         Thread t = Thread.currentThread();
 159         ThreadLocalMap map = getMap(t);
 160         if (map != null) {
 161             ThreadLocalMap.Entry e = map.getEntry(this);
 162             if (e != null) {
 163                 @SuppressWarnings("unchecked")
 164                 T result = (T)e.value;


 193      *
 194      * @param value the value to be stored in the current thread's copy of
 195      *        this thread-local.
 196      */
 197     public void set(T value) {
 198         Thread t = Thread.currentThread();
 199         ThreadLocalMap map = getMap(t);
 200         if (map != null)
 201             map.set(this, value);
 202         else
 203             createMap(t, value);
 204     }
 205 
 206     /**
 207      * Removes the current thread's value for this thread-local
 208      * variable.  If this thread-local variable is subsequently
 209      * {@linkplain #get read} by the current thread, its value will be
 210      * reinitialized by invoking its {@link #initialValue} method,
 211      * unless its value is {@linkplain #set set} by the current thread
 212      * in the interim.  This may result in multiple invocations of the
 213      * {@code initialValue} method in the current thread.
 214      *
 215      * @since 1.5
 216      */
 217      public void remove() {
 218          ThreadLocalMap m = getMap(Thread.currentThread());
 219          if (m != null)
 220              m.remove(this);
 221      }
 222 
 223     /**
 224      * Get the map associated with a ThreadLocal. Overridden in
 225      * InheritableThreadLocal.
 226      *
 227      * @param  t the current thread
 228      * @return the map
 229      */
 230     ThreadLocalMap getMap(Thread t) {
 231         return t.threadLocals;
 232     }
 233 


 249      * @param  parentMap the map associated with parent thread
 250      * @return a map containing the parent's inheritable bindings
 251      */
 252     static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
 253         return new ThreadLocalMap(parentMap);
 254     }
 255 
 256     /**
 257      * Method childValue is visibly defined in subclass
 258      * InheritableThreadLocal, but is internally defined here for the
 259      * sake of providing createInheritedMap factory method without
 260      * needing to subclass the map class in InheritableThreadLocal.
 261      * This technique is preferable to the alternative of embedding
 262      * instanceof tests in methods.
 263      */
 264     T childValue(T parentValue) {
 265         throw new UnsupportedOperationException();
 266     }
 267 
 268     /**
 269      * An extension of ThreadLocal that obtains its initial value from
 270      * the specified {@code Supplier}.
 271      */
 272     static final class SuppliedThreadLocal<T> extends ThreadLocal<T> {
 273 
 274         private final Supplier<? extends T> supplier;
 275 
 276         SuppliedThreadLocal(Supplier<? extends T> supplier) {
 277             this.supplier = Objects.requireNonNull(supplier);
 278         }
 279 
 280         @Override
 281         protected T initialValue() {
 282             return supplier.get();
 283         }
 284     }
 285 
 286     /**
 287      * ThreadLocalMap is a customized hash map suitable only for
 288      * maintaining thread local values. No operations are exported
 289      * outside of the ThreadLocal class. The class is package private to
 290      * allow declaration of fields in class Thread.  To help deal with
 291      * very large and long-lived usages, the hash table entries use
 292      * WeakReferences for keys. However, since reference queues are not
 293      * used, stale entries are guaranteed to be removed only when
 294      * the table starts running out of space.
 295      */
 296     static class ThreadLocalMap {
 297 
 298         /**
 299          * The entries in this hash map extend WeakReference, using
 300          * its main ref field as the key (which is always a
 301          * ThreadLocal object).  Note that null keys (i.e. entry.get()
 302          * == null) mean that the key is no longer referenced, so the
 303          * entry can be expunged from table.  Such entries are referred to
 304          * as "stale entries" in the code that follows.
 305          */
 306         static class Entry extends WeakReference<ThreadLocal<?>> {


 615                             h = nextIndex(h, len);
 616                         tab[h] = e;
 617                     }
 618                 }
 619             }
 620             return i;
 621         }
 622 
 623         /**
 624          * Heuristically scan some cells looking for stale entries.
 625          * This is invoked when either a new element is added, or
 626          * another stale one has been expunged. It performs a
 627          * logarithmic number of scans, as a balance between no
 628          * scanning (fast but retains garbage) and a number of scans
 629          * proportional to number of elements, that would find all
 630          * garbage but would cause some insertions to take O(n) time.
 631          *
 632          * @param i a position known NOT to hold a stale entry. The
 633          * scan starts at the element after i.
 634          *
 635          * @param n scan control: {@code log2(n)} cells are scanned,
 636          * unless a stale entry is found, in which case
 637          * {@code log2(table.length)-1} additional cells are scanned.
 638          * When called from insertions, this parameter is the number
 639          * of elements, but when from replaceStaleEntry, it is the
 640          * table length. (Note: all this could be changed to be either
 641          * more or less aggressive by weighting n instead of just
 642          * using straight log n. But this version is simple, fast, and
 643          * seems to work well.)
 644          *
 645          * @return true if any stale entries have been removed.
 646          */
 647         private boolean cleanSomeSlots(int i, int n) {
 648             boolean removed = false;
 649             Entry[] tab = table;
 650             int len = tab.length;
 651             do {
 652                 i = nextIndex(i, len);
 653                 Entry e = tab[i];
 654                 if (e != null && e.get() == null) {
 655                     n = len;
 656                     removed = true;
 657                     i = expungeStaleEntry(i);