代码之家  ›  专栏  ›  技术社区  ›  Jonas N

没有迭代或复制Java线程本地的所有值的方法吗?

  •  4
  • Jonas N  · 技术社区  · 16 年前

    语境:

    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...]
    }
    
    3 回复  |  直到 8 年前
        1
  •  6
  •   Bozho    16 年前

    一种方法是手动处理:

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

    或者,有一些思考( getDeclaredMethod() setAccessible(true) 你可以:

    • 呼叫 Thread.getThreads()
    • 呼叫 yourThreadLocal.getMap(thread) (对于上述每一个螺纹)
    • 呼叫 map.getEntry(yourThreadLocal)

    第一个更可取。

        2
  •  1
  •   doublep    16 年前

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

    正如bozho所建议的,您可以通过子类化来做到这一点。 线程本地 在其他地方复制值。别忘了正确地同步对“其他地方”的访问。

        3
  •  1
  •   Sina Madani    8 年前

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

    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();
        }
    }
    

    编辑:如果计划将此与ThreadPool执行器一起使用,请更改 WeakHashMap 定期 HashMap 否则会发生奇怪的事情!