37 |
|
|
38 |
package java.lang; |
package java.lang; |
39 |
|
|
|
import java.util.Collections; |
|
40 |
import java.util.Map; |
import java.util.Map; |
41 |
import java.util.WeakHashMap; |
import java.util.WeakHashMap; |
42 |
|
|
97 |
static final Object NULL = new Object(); |
static final Object NULL = new Object(); |
98 |
|
|
99 |
/** |
/** |
100 |
* The stored value. Package visible for use by InheritableThreadLocal. */ |
* Serves as a key for the Thread.locals WeakHashMap. |
101 |
T value; |
* We can't use "this", because a subclass may override equals/hashCode |
102 |
|
* and we need to use object identity for the map. |
|
/** |
|
|
* Maps Threads to values. Uses a WeakHashMap so if a Thread is garbage |
|
|
* collected the reference to the Value will disappear. A null value means |
|
|
* uninitialized, while NULL means a user-specified null. Only the |
|
|
* <code>set(Thread, Object)</code> and <code>get(Thread)</code> methods |
|
|
* access it. Package visible for use by InheritableThreadLocal. |
|
103 |
*/ |
*/ |
104 |
final Map<Thread, T> valueMap |
final Key key = new Key(); |
105 |
= Collections.synchronizedMap(new WeakHashMap<Thread, T>()); |
|
106 |
|
class Key |
107 |
|
{ |
108 |
|
ThreadLocal get() |
109 |
|
{ |
110 |
|
return ThreadLocal.this; |
111 |
|
} |
112 |
|
} |
113 |
|
|
114 |
|
|
115 |
/** |
/** |
116 |
* Creates a ThreadLocal object without associating any value to it yet. |
* Creates a ThreadLocal object without associating any value to it yet. |
142 |
*/ |
*/ |
143 |
public T get() |
public T get() |
144 |
{ |
{ |
145 |
Thread currentThread = Thread.currentThread(); |
Map<Key,T> map = (Map<Key,T>) Thread.getThreadLocals(); |
146 |
// Note that we don't have to synchronize, as only this thread will |
// Note that we don't have to synchronize, as only this thread will |
147 |
// ever modify the returned value and valueMap is a synchronizedMap. |
// ever modify the map. |
148 |
T value = valueMap.get(currentThread); |
T value = map.get(key); |
149 |
if (value == null) |
if (value == null) |
150 |
{ |
{ |
151 |
value = initialValue(); |
value = initialValue(); |
152 |
valueMap.put(currentThread, value == null ? (T) NULL : value); |
map.put(key, value == null ? (T) NULL : value); |
153 |
} |
} |
154 |
return value == (T) NULL ? null : value; |
return value == (T) NULL ? null : value; |
155 |
} |
} |
164 |
*/ |
*/ |
165 |
public void set(T value) |
public void set(T value) |
166 |
{ |
{ |
167 |
|
Map map = Thread.getThreadLocals(); |
168 |
// Note that we don't have to synchronize, as only this thread will |
// Note that we don't have to synchronize, as only this thread will |
169 |
// ever modify the returned value and valueMap is a synchronizedMap. |
// ever modify the map. |
170 |
valueMap.put(Thread.currentThread(), value == null ? (T) NULL : value); |
map.put(key, value == null ? NULL : value); |
171 |
} |
} |
172 |
} |
} |