Threadlocal remove? Threadlocal remove? multithreading multithreading

Threadlocal remove?


Because ThreadLocal has Map of currentThread and value, Now if you don't remove the value in the thread which was using it then it will create a memory leak.

You should always call remove because ThreadLocal class puts values from the Thread Class defined by ThreadLocal.Values localValues; This will also cause to hold reference of Thread and associated objects.

From the source code of ThreadLocal

the value will be set to null and the underlying entry will still be present.


set always replaces the old value.

This is true for

  • Calendar.set() and Date.set()
  • BitSet.set()
  • List.set()
  • setters

You mean without remove it will not be GCed?

It will not be removed until the thread dies. It won't disappear on you without you calling remove()

Whether this is a memory leak or not depends on your program. You would have to create lots of threads with large thread local objects which you didn't need for some reason for it to matter. e.g. 1000 threads with a 1 KB object could waste up to 1 MB, but this suggest a design issue if you are doing this sort of thing.


The only place you might get a memory leak is.

for (int i = 0; ; i++) {    // don't subclass Thread.    new Thread() {        // this is somewhat pointless as you are defining a ThreadLocal per thread.        final ThreadLocal<Object> tlObject = new ThreadLocal<Object>() {        };        public void run() {            tlObject.set(new byte[8 * 1024 * 1024]);        }    }.start();    Thread.sleep(1);    if (i % 1000 == 0) {        System.gc();        System.out.println(i);    }}

with -verbosegc prints.

[Full GC 213548K->49484K(3832192K), 0.0334194 secs]39000[GC 2786060K->82412K(3836864K), 0.0132035 secs][GC 2815569K->107052K(3836544K), 0.0212252 secs][GC 2836162K->131628K(3837824K), 0.0199268 secs][GC 2867613K->156204K(3837568K), 0.0209828 secs][GC 2886894K->180780K(3838272K), 0.0191244 secs][GC 2911942K->205356K(3838080K), 0.0187482 secs][GC 421535K->229932K(3838208K), 0.0192605 secs][Full GC 229932K->49484K(3838208K), 0.0344509 secs]40000

Note: the size after a full GC is the same 49484K

In the above case you will have a ThreadLocal which refers to the Thread which refers to the ThreadLocal. However, as the Thread is dead it doesn't cause a memory leak becasue it becomes a regard object i.e. when A -> B and B -> A

I ran the above example in a loop for a couple of minutes and the GC levels moved around alot but the minimum size was still small.


No you do not have to "always call remove()" instead of set()

If you fear memory leaks doing so, here is what the javadoc says

Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).

Thus not calling remove() will not prevent a thread-local instance to be properly garbage collected, and will not cause memory leaks by nature.

You can also take a look to ThreadLocal implementation, which use WeakReferences for this "implicit reference" mechanism

But beware of consistency with thread pools

Using set() method only with a thread pool, you might prefer to remove() a ThreadLocal instance, instead of overriding it in another "work unit" using the same thread.Because you might want to avoid the situation where, for some reason, the set method is not invoked, and your ThreadLocal remains attached to a context/treatment it does not belong.