有没有办法迭代或复制Java ThreadLocal的所有值?

语境:

static ThreadLocal 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...] } 

一种方法是手动处理:

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

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

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

第一是更优选的。

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

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

我遇到了同样的问题,看到这里的答案后,我决定使用混合方法:

 public class PersistentThreadLocal extends ThreadLocal { final Map allValues; final Supplier valueGetter; public PersistentThreadLocal(Supplier initialValue) { this(0, initialValue); } public PersistentThreadLocal(int numThreads, Supplier 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 getAll() { return allValues.values(); } public void clear() { allValues.clear(); } } 

编辑:如果您计划将此与ThreadPoolExecutor一起使用,请将WeakHashMap更改为常规HashMap ,否则会发生奇怪的事情!