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!
ThreadLocal
, you don't want aThreadLocal
at all. Generally, you want aConcurrentHashMap<Thread, MyType>
. – PhycomyceteCache
. – Phycomycete