Class CloseableThreadLocal<T>
java.lang.Object
net.imglib2.util.CloseableThreadLocal<T>
- All Implemented Interfaces:
Closeable, AutoCloseable
- Direct Known Subclasses:
CloseableThreadLocal.SuppliedCloseableThreadLocal
Java's builtin ThreadLocal has a serious flaw: it can take an arbitrarily long amount of time to
dereference the things you had stored in it, even once the ThreadLocal instance itself is no
longer referenced. This is because there is single, master map stored for each thread, which all
ThreadLocals share, and that master map only periodically purges "stale" entries.
While not technically a memory leak, because eventually the memory will be reclaimed, it can take a long time and you can easily hit OutOfMemoryError because from the GC's standpoint the stale entries are not reclaimable.
This class works around that, by only enrolling WeakReference values into the ThreadLocal, and
separately holding a hard reference to each stored value. When you call close(), these
hard references are cleared and then GC is freely able to reclaim space by objects stored in it.
We can not rely on ThreadLocal.remove() as it only removes the value for the caller
thread, whereas close() takes care of all threads. You should not call close()
until all threads are done using the instance.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescription(package private) static final class -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate final AtomicIntegerprivate static intprivate ThreadLocal<WeakReference<T>> -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidclose()get()protected Tprivate voidprivate voidpurge()voidstatic <S> CloseableThreadLocal<S> withInitial(Supplier<? extends S> supplier) Creates a thread local variable.
-
Field Details
-
t
-
hardRefs
-
PURGE_MULTIPLIER
private static int PURGE_MULTIPLIER -
countUntilPurge
-
-
Constructor Details
-
CloseableThreadLocal
public CloseableThreadLocal()
-
-
Method Details
-
withInitial
Creates a thread local variable. The initial value of the variable is determined by invoking thegetmethod on theSupplier. -
initialValue
-
get
-
set
-
maybePurge
private void maybePurge() -
purge
private void purge() -
close
public void close()- Specified by:
closein interfaceAutoCloseable- Specified by:
closein interfaceCloseable
-