5

语境:

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...]
}
4

3 回答 3

7

一种方法是手动处理:

  • 使用ThreadLocal(扩展它)的包装器
  • 每当设置一个值时,保留一个 ( static)Map线程和值

或者,通过一些反射(getDeclaredMethod()setAccessible(true)),您可以:

  • 称呼Thread.getThreads()
  • 调用yourThreadLocal.getMap(thread)(对于上述每个线程)
  • 称呼map.getEntry(yourThreadLocal)

第一种更优选。

于 2010-05-08T20:30:03.710 回答
1

不,因为在内部它的实现方式不同:每个线程都有一个类似于地图的本地人。如果允许,您想要做的事情本质上是线程不安全的。ThreadLocal每个线程在访问自己的本地时显然不使用任何类型的同步:没有其他线程可以做到这一点,因此不需要同步。出于这个原因,从任何其他线程(如果可能的话)访问本地映射将是线程不安全的。

正如 Bozho 建议的那样,您可以通过在ThreadLocal其他地方子类化和复制值来做到这一点。不要忘记正确同步对“其他地方”的访问。

于 2010-05-08T20:36:58.087 回答
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();
    }
}

EDIT: if you plan to use this with a ThreadPoolExecutor, change the WeakHashMap to a regular HashMap, otherwise strange things will happen!

于 2017-11-13T15:28:48.377 回答