On the first picture to look at the internal structure of ThreadLocal, each Thread objects internal maintains a ThreadLocal. ThreadLocalMap
What we see in the figure above is the ThreadLocalMap of the cells inside the three Thread objects
When a ThreadLocal is used, a WeakReference is used
static class ThreadLocalMap { static class Entry extends WeakReference<ThreadLocal<? >> { Entry(ThreadLocal<? > k, Object v) { super(k); value = v; }Copy the code
A weak reference WeakReference
Weak references are reclaimed whenever GC occurs, but only if there are weak references and no strong references (which itself is not easy to do)
WeakReference<Apple> weakReference = new WeakReference<>(new Apple("1")); try { Thread.sleep(2000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(weakReference.get()); //1 System.gc(); System.out.println(weakReference.get())); //nullCopy the code
Special case of reference passing
1. If the input parameter passed is null, it will not affect the object outside the method that is not null. Set the input parameter to NULL outside the thread, and continue not null inside the thread. null ! Null to NULL does not affect the original layer
// We will insert only a simulated thread running case here... obj = new ObjectPassing(); obj.setName("name"); MyThread myThread = new MyThread(obj); //obj is not an empty incoming Thread new Thread(myThread).start(); Thread.sleep(1000); thread.sleep (1000); obj = null; System.out.println("2:"+obj); // Set the outer obj to null. Thread.sleep(1000000); } public void testNullPassFunc(ObjectPassing obj){ obj = new ObjectPassing(); obj.setName("zxp"); System.out.println("2:"+obj); } public void testNullPassFunc2(ObjectPassing obj){ obj = null; System.out.println("2:"+obj); } @Data static class ObjectPassing{ private String name; } 1:null 2:ParameterPassing.ObjectPassing(name=zxp) 3:null ======================= 1:ParameterPassing.ObjectPassing(name=name) 2:null 3:ParameterPassing.ObjectPassing(name=name) ======================= 1:name 1:name 2: NULL 1:name 1:name 1:name......Copy the code
public class MyThread implements Runnable { ParameterPassing.ObjectPassing objectPassing = null; public MyThread(ParameterPassing.ObjectPassing objectPassing){ this.objectPassing = objectPassing; } @Override public void run() { while (true){ System.out.println("1:"+objectPassing.getName()); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); }}}}Copy the code
Analyze ThreadLocal and WeakReference
Why does ThreadLocal use WeakReference
ThreadLocal local = new ThreadLocal(); Local.set (" currentThread name: "+ thread.currentthread ().getname ()); Thread t = thread.currentThread (); Local = null; // Local = null; // Local = null; // Local = null; // When the Entry is set to null, the result in the Entry cannot be affected. System.gc(); // execute GC t = thread.currentThread (); // At this time, the Entry referent is null, which is removed by GC, because the relationship between Entry and key is WeakReference, and it is reclaimed without other strong reference. If the thread runs for a very long time, even if the referent GC is performed, the value does not clear. Remove () : local.remove(); System.out.println(local); system.out.println (local);Copy the code