背景:
static ThreadLocal<MyType> threadLocalMyType = ...
我想说的是:
for (ThreadLocalEntry e: threadLocalMyType.getMapLikeThing() {
// Thread t = e.getKey();
// I don't need the thread value right now, but it might be useful for
// something else.
MyType theMyType = e.getValue();
// [...do something with theMyType...]
}
答案 0 :(得分:6)
一种方法是手动处理:
ThreadLocal
(扩展名)static
)Map
主题和值或者,通过一些反思(getDeclaredMethod()
和setAccessible(true)
),您可以:
Thread.getThreads()
yourThreadLocal.getMap(thread)
(针对以上每个主题)map.getEntry(yourThreadLocal)
第一是更优选的。
答案 1 :(得分:1)
不,因为在内部它的实现方式不同:每个线程都有一个类似于地图的地图。如果ThreadLocal
允许,您想要做的就是固有的线程不安全。在访问自己的本地时,每个线程显然不使用任何类型的同步:没有其他线程可以做到这一点,因此不需要同步。出于这个原因,从任何其他线程(如果可能的话)访问本地映射将是线程不安全的。
正如Bozho建议的那样,你可以通过继承ThreadLocal
并在其他地方复制值来做到这一点。不要忘记正确地同步访问“其他地方”。
答案 2 :(得分:0)
我遇到同样的问题,在看到这里的答案后,我决定使用混合方法:
public class PersistentThreadLocal<T> extends ThreadLocal<T> {
final Map<Thread, T> allValues;
final Supplier<? extends T> valueGetter;
public PersistentThreadLocal(Supplier<? extends T> initialValue) {
this(0, initialValue);
}
public PersistentThreadLocal(int numThreads, Supplier<? extends T> initialValue) {
allValues = Collections.synchronizedMap(
numThreads > 0 ? new WeakHashMap<>(numThreads) : new WeakHashMap<>()
);
valueGetter = initialValue;
}
@Override
protected T initialValue() {
T value = valueGetter != null ? valueGetter.get() : super.initialValue();
allValues.put(Thread.currentThread(), value);
return value;
}
@Override
public void set(T value) {
super.set(value);
allValues.put(Thread.currentThread(), value);
}
@Override
public void remove() {
super.remove();
allValues.remove(Thread.currentThread());
}
public Collection<T> getAll() {
return allValues.values();
}
public void clear() {
allValues.clear();
}
}
编辑:如果您计划将此项与ThreadPoolExecutor一起使用,请将WeakHashMap
更改为常规HashMap
,否则会发生奇怪的事情!