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 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: }