jtulach@1280: /* jtulach@1280: * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. jtulach@1280: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jtulach@1280: * jtulach@1280: * This code is free software; you can redistribute it and/or modify it jtulach@1280: * under the terms of the GNU General Public License version 2 only, as jtulach@1280: * published by the Free Software Foundation. Oracle designates this jtulach@1280: * particular file as subject to the "Classpath" exception as provided jtulach@1280: * by Oracle in the LICENSE file that accompanied this code. jtulach@1280: * jtulach@1280: * This code is distributed in the hope that it will be useful, but WITHOUT jtulach@1280: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jtulach@1280: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jtulach@1280: * version 2 for more details (a copy is included in the LICENSE file that jtulach@1280: * accompanied this code). jtulach@1280: * jtulach@1280: * You should have received a copy of the GNU General Public License version jtulach@1280: * 2 along with this work; if not, write to the Free Software Foundation, jtulach@1280: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jtulach@1280: * jtulach@1280: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jtulach@1280: * or visit www.oracle.com if you need additional information or have any jtulach@1280: * questions. jtulach@1280: */ jtulach@1280: jtulach@1280: package java.lang; jtulach@1280: jtulach@1280: /** jtulach@1280: * This class provides thread-local variables. These variables differ from jtulach@1280: * their normal counterparts in that each thread that accesses one (via its jtulach@1280: * get or set method) has its own, independently initialized jtulach@1280: * copy of the variable. ThreadLocal instances are typically private jtulach@1280: * static fields in classes that wish to associate state with a thread (e.g., jtulach@1280: * a user ID or Transaction ID). jtulach@1280: * jtulach@1280: *

For example, the class below generates unique identifiers local to each jtulach@1280: * thread. jtulach@1280: * A thread's id is assigned the first time it invokes ThreadId.get() jtulach@1280: * and remains unchanged on subsequent calls. jtulach@1280: *

jtulach@1280:  * import java.util.concurrent.atomic.AtomicInteger;
jtulach@1280:  *
jtulach@1280:  * public class ThreadId {
jtulach@1280:  *     // Atomic integer containing the next thread ID to be assigned
jtulach@1280:  *     private static final AtomicInteger nextId = new AtomicInteger(0);
jtulach@1280:  *
jtulach@1280:  *     // Thread local variable containing each thread's ID
jtulach@1280:  *     private static final ThreadLocal<Integer> threadId =
jtulach@1280:  *         new ThreadLocal<Integer>() {
jtulach@1280:  *             @Override protected Integer initialValue() {
jtulach@1280:  *                 return nextId.getAndIncrement();
jtulach@1280:  *         }
jtulach@1280:  *     };
jtulach@1280:  *
jtulach@1280:  *     // Returns the current thread's unique ID, assigning it if necessary
jtulach@1280:  *     public static int get() {
jtulach@1280:  *         return threadId.get();
jtulach@1280:  *     }
jtulach@1280:  * }
jtulach@1280:  * 
jtulach@1280: *

Each thread holds an implicit reference to its copy of a thread-local jtulach@1280: * variable as long as the thread is alive and the ThreadLocal jtulach@1280: * instance is accessible; after a thread goes away, all of its copies of jtulach@1280: * thread-local instances are subject to garbage collection (unless other jtulach@1280: * references to these copies exist). jtulach@1280: * jtulach@1280: * @author Josh Bloch and Doug Lea jtulach@1280: * @since 1.2 jtulach@1280: */ jtulach@1280: public class ThreadLocal { jtulach@1281: private static final Object NONE = new Object(); jtulach@1281: private Object value = NONE; jtulach@1281: jtulach@1280: /** jtulach@1280: * Returns the current thread's "initial value" for this jtulach@1280: * thread-local variable. This method will be invoked the first jtulach@1280: * time a thread accesses the variable with the {@link #get} jtulach@1280: * method, unless the thread previously invoked the {@link #set} jtulach@1280: * method, in which case the initialValue method will not jtulach@1280: * be invoked for the thread. Normally, this method is invoked at jtulach@1280: * most once per thread, but it may be invoked again in case of jtulach@1280: * subsequent invocations of {@link #remove} followed by {@link #get}. jtulach@1280: * jtulach@1280: *

This implementation simply returns null; if the jtulach@1280: * programmer desires thread-local variables to have an initial jtulach@1280: * value other than null, ThreadLocal must be jtulach@1280: * subclassed, and this method overridden. Typically, an jtulach@1280: * anonymous inner class will be used. jtulach@1280: * jtulach@1280: * @return the initial value for this thread-local jtulach@1280: */ jtulach@1280: protected T initialValue() { jtulach@1280: return null; jtulach@1280: } jtulach@1280: jtulach@1280: /** jtulach@1280: * Creates a thread local variable. jtulach@1280: */ jtulach@1280: public ThreadLocal() { jtulach@1280: } jtulach@1280: jtulach@1280: /** jtulach@1280: * Returns the value in the current thread's copy of this jtulach@1280: * thread-local variable. If the variable has no value for the jtulach@1280: * current thread, it is first initialized to the value returned jtulach@1280: * by an invocation of the {@link #initialValue} method. jtulach@1280: * jtulach@1280: * @return the current thread's value of this thread-local jtulach@1280: */ jtulach@1280: public T get() { jtulach@1281: if (value == NONE) { jtulach@1281: return setInitialValue(); jtulach@1281: } else { jtulach@1281: return (T)value; jtulach@1280: } jtulach@1280: } jtulach@1280: jtulach@1280: /** jtulach@1280: * Variant of set() to establish initialValue. Used instead jtulach@1280: * of set() in case user has overridden the set() method. jtulach@1280: * jtulach@1280: * @return the initial value jtulach@1280: */ jtulach@1280: private T setInitialValue() { jtulach@1281: T v = initialValue(); jtulach@1281: this.value = v; jtulach@1281: return v; jtulach@1280: } jtulach@1280: jtulach@1280: /** jtulach@1280: * Sets the current thread's copy of this thread-local variable jtulach@1280: * to the specified value. Most subclasses will have no need to jtulach@1280: * override this method, relying solely on the {@link #initialValue} jtulach@1280: * method to set the values of thread-locals. jtulach@1280: * jtulach@1280: * @param value the value to be stored in the current thread's copy of jtulach@1280: * this thread-local. jtulach@1280: */ jtulach@1280: public void set(T value) { jtulach@1281: this.value = value; jtulach@1280: } jtulach@1280: jtulach@1280: /** jtulach@1280: * Removes the current thread's value for this thread-local jtulach@1280: * variable. If this thread-local variable is subsequently jtulach@1280: * {@linkplain #get read} by the current thread, its value will be jtulach@1280: * reinitialized by invoking its {@link #initialValue} method, jtulach@1280: * unless its value is {@linkplain #set set} by the current thread jtulach@1280: * in the interim. This may result in multiple invocations of the jtulach@1280: * initialValue method in the current thread. jtulach@1280: * jtulach@1280: * @since 1.5 jtulach@1280: */ jtulach@1280: public void remove() { jtulach@1281: this.value = NONE; jtulach@1280: } jtulach@1280: }