7 * published by the Free Software Foundation. Oracle designates this 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 * 154 * current thread, it is first initialized to the value returned 155 * by an invocation of the {@link #initialValue} method. 156 * 157 * @return the current thread's value of this thread-local 158 */ 159 public T get() { 160 Thread t = Thread.currentThread(); 161 ThreadLocalMap map = getMap(t); 162 if (map != null) { 163 ThreadLocalMap.Entry e = map.getEntry(this); 164 if (e != null) { 165 @SuppressWarnings("unchecked") 166 T result = (T)e.value; 167 return result; 168 } 169 } 170 return setInitialValue(); 171 } 172 173 /** 174 * Variant of set() to establish initialValue. Used instead 175 * of set() in case user has overridden the set() method. 176 * 177 * @return the initial value 178 */ 179 private T setInitialValue() { 180 T value = initialValue(); 181 Thread t = Thread.currentThread(); 182 ThreadLocalMap map = getMap(t); 183 if (map != null) 184 map.set(this, value); 185 else 186 createMap(t, value); 187 return value; 188 } 189 190 /** 191 * Sets the current thread's copy of this thread-local variable 192 * to the specified value. Most subclasses will have no need to 193 * override this method, relying solely on the {@link #initialValue} 194 * method to set the values of thread-locals. 195 * 196 * @param value the value to be stored in the current thread's copy of 197 * this thread-local. 198 */ 199 public void set(T value) { 200 Thread t = Thread.currentThread(); 201 ThreadLocalMap map = getMap(t); 202 if (map != null) 203 map.set(this, value); 204 else 205 createMap(t, value); 206 } | 7 * published by the Free Software Foundation. Oracle designates this 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 jdk.internal.misc.TerminatingThreadLocal; 28 29 import java.lang.ref.*; 30 import java.util.Objects; 31 import java.util.concurrent.atomic.AtomicInteger; 32 import java.util.function.Supplier; 33 34 /** 35 * This class provides thread-local variables. These variables differ from 36 * their normal counterparts in that each thread that accesses one (via its 37 * {@code get} or {@code set} method) has its own, independently initialized 38 * copy of the variable. {@code ThreadLocal} instances are typically private 39 * static fields in classes that wish to associate state with a thread (e.g., 40 * a user ID or Transaction ID). 41 * 42 * <p>For example, the class below generates unique identifiers local to each 43 * thread. 44 * A thread's id is assigned the first time it invokes {@code ThreadId.get()} 45 * and remains unchanged on subsequent calls. 46 * <pre> 47 * import java.util.concurrent.atomic.AtomicInteger; 48 * 156 * current thread, it is first initialized to the value returned 157 * by an invocation of the {@link #initialValue} method. 158 * 159 * @return the current thread's value of this thread-local 160 */ 161 public T get() { 162 Thread t = Thread.currentThread(); 163 ThreadLocalMap map = getMap(t); 164 if (map != null) { 165 ThreadLocalMap.Entry e = map.getEntry(this); 166 if (e != null) { 167 @SuppressWarnings("unchecked") 168 T result = (T)e.value; 169 return result; 170 } 171 } 172 return setInitialValue(); 173 } 174 175 /** 176 * Returns {@code true} if there is a value in the current thread's copy of 177 * this thread-local variable, even if that values is {@code null}. 178 * 179 * @return {@code true} if current thread has associated value in this 180 * thread-local variable; {@code false} if not 181 */ 182 boolean isPresent() { 183 Thread t = Thread.currentThread(); 184 ThreadLocalMap map = getMap(t); 185 return map != null && map.getEntry(this) != null; 186 } 187 188 /** 189 * Variant of set() to establish initialValue. Used instead 190 * of set() in case user has overridden the set() method. 191 * 192 * @return the initial value 193 */ 194 private T setInitialValue() { 195 T value = initialValue(); 196 Thread t = Thread.currentThread(); 197 ThreadLocalMap map = getMap(t); 198 if (map != null) 199 map.set(this, value); 200 else 201 createMap(t, value); 202 TerminatingThreadLocal.register(this); 203 return value; 204 } 205 206 /** 207 * Sets the current thread's copy of this thread-local variable 208 * to the specified value. Most subclasses will have no need to 209 * override this method, relying solely on the {@link #initialValue} 210 * method to set the values of thread-locals. 211 * 212 * @param value the value to be stored in the current thread's copy of 213 * this thread-local. 214 */ 215 public void set(T value) { 216 Thread t = Thread.currentThread(); 217 ThreadLocalMap map = getMap(t); 218 if (map != null) 219 map.set(this, value); 220 else 221 createMap(t, value); 222 } |