Is there no way to iterate over or copy all the values of a Java ThreadLocal?

前端 未结 3 1225
执念已碎
执念已碎 2020-12-19 12:26

Context:

static ThreadLocal threadLocalMyType = ...

What i\'d like is to say something like:

for (ThreadLoc         


        
相关标签:
3条回答
  • 2020-12-19 12:35

    I came acrosss the same problem and after seeing the answers here, I decided to use a hybrid approach:

    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!

    0 讨论(0)
  • 2020-12-19 12:47

    One way would be to handle this manually:

    • use a wrapper of ThreadLocal (extend it)
    • whenever a value is set, keep a (static) Map of Threads and values

    Alternatively, with some reflection (getDeclaredMethod() and setAccessible(true)), you can:

    • call Thread.getThreads()
    • call yourThreadLocal.getMap(thread) (for each of the above threads)
    • call map.getEntry(yourThreadLocal)

    The 1st is more preferable.

    0 讨论(0)
  • 2020-12-19 12:50

    No, because internally it is implement differently: each thread has a map-like thing of its locals. What you want to do would be inherently thread-unsafe if ThreadLocal allowed it. Each thread obviously doesn't use any kind of synchronization when accessing its own locals: no other thread can do that, so synchronization is not needed. For this reason, accessing the locals map from any other thread (if that was possible) would be thread-unsafe.

    As Bozho suggested, you could do that by subclassing ThreadLocal and duplicating values somewhere else. Don't forget to synchronize access to that "somewhere else" properly.

    0 讨论(0)
提交回复
热议问题