Class CloseableThreadLocal<T>

  • All Implemented Interfaces:
    java.io.Closeable, java.lang.AutoCloseable

    public class CloseableThreadLocal<T>
    extends java.lang.Object
    implements java.io.Closeable
    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.
    • Field Summary

      Fields 
      Modifier and Type Field Description
      private java.util.concurrent.atomic.AtomicInteger countUntilPurge  
      private java.util.Map<java.lang.Thread,​T> hardRefs  
      private static int PURGE_MULTIPLIER  
      private java.lang.ThreadLocal<java.lang.ref.WeakReference<T>> t  
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void close()  
      T get()  
      protected T initialValue()  
      private void maybePurge()  
      private void purge()  
      void set​(T object)  
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Field Detail

      • t

        private java.lang.ThreadLocal<java.lang.ref.WeakReference<T>> t
      • hardRefs

        private java.util.Map<java.lang.Thread,​T> hardRefs
      • PURGE_MULTIPLIER

        private static int PURGE_MULTIPLIER
      • countUntilPurge

        private final java.util.concurrent.atomic.AtomicInteger countUntilPurge
    • Constructor Detail

      • CloseableThreadLocal

        public CloseableThreadLocal()
    • Method Detail

      • initialValue

        protected T initialValue()
      • get

        public T get()
      • set

        public void set​(T object)
      • maybePurge

        private void maybePurge()
      • purge

        private void purge()
      • close

        public void close()
        Specified by:
        close in interface java.lang.AutoCloseable
        Specified by:
        close in interface java.io.Closeable