TheadLocal源码分析

源码思维导图:https://www.processon.com/view/link/64194d2bc707d756390b0e40

demo案例

   @Test
    public void testThread() throws InterruptedException {
        HashMap<String, Integer> hashMapA = new HashMap<>();
        HashMap<String, Integer> hashMapB = new HashMap<>();
        HashMap<String, Integer> hashMapC = new HashMap<>();

        Thread threadA = new Thread( new Runnable() {
            @Override
            public void run() {
                System.out.println("A线程开始执行!"+Thread.currentThread().getName());
                hashMapA.put("A线程",1);
                threadLocal.set(hashMapA);
                Map map = threadLocal.get();
                System.out.println("A线程threadLocal:"+map);
            }
        });
        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("B线程开始执行!"+Thread.currentThread().getName());
                hashMapB.put("B线程",1);
                threadLocal.set(hashMapB);
                Map map = threadLocal.get();
                    System.out.println("B线程threadLocal:"+map);
            }
        });

        hashMapC.put("C线程:",1);
        threadLocal.set(hashMapC);

        threadA.start();
        threadB.start();

        Map map = threadLocal.get();
        System.out.println("main线程开始执行!"+Thread.currentThread().getName());
        System.out.println("main线程threadLocal:"+map);

    }

输出

main线程开始执行!main
A线程开始执行!Thread-0
B线程开始执行!Thread-1
main线程threadLocal:{C线程:=1}
A线程threadLocal:{A线程=1}
B线程threadLocal:{B线程=1}

Reference状态

Reference 有五个成员变量:

referent,queue,pending,next,discovered

Reference对象所处状态不同,成员变量的值也会变化。

  • Active: Reference对象新建时处于该状态。

  • Pending: 当Reference包装的referent = null的时候,JVM会把Reference设置成pending状态。如果Reference创建时指定了ReferenceQueue,那么会被ReferenceHandler线程处理进入到ReferenceQueue队列中,如果没有就进入Inactive状态。

  • Enqueue: 进入ReferenceQueue中的对象,等待被回收

  • Inactive: Reference对象从ReferenceQueue取出来并被处理掉。处于Inactive的Reference对象状态不能再改变

    状态的编码由域queue和next共同完成:

    • Active状态
      queue = ReferenceQueue 实例创建时注册;ReferenceQueue.NULL未注册;
      next = null
    • Pengding状态
      queue = ReferenceQueue 实例创建时注册
      next = this
    • Enqueued状态
      queue = ReferenceQueue.ENQUEUEd
      next = queue中下一个实例,若是链表list末尾,则是this
    • Inactive状态
      queue = ReferenceQueue.NULL
      next = this

img

4种引用类型

强,软,弱,虚

1、强引用

例:

Object obj=new Object();
1
强引⽤是使用最普遍的引用。如果⼀个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引⽤的对象来解决内存不足的问题。
1

2、软引用(SoftReference)

例:

Object obj = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null;
sf.get();//获取对象
1234
如果内存空间不足了,就会回收这些对象的内存。软引用可以和⼀个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加⼊到与之关联的引用队列中。
1

3、弱引用(WeakReference)

例:

Object obj = new Object();
WeakReference<Object> wf = new WeakReference<Object>(obj);
wf.get();//获取对象
123
 弱引⽤与软引用的区别在于:只具有弱引用的对象拥有更短暂的⽣命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,⼀旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。弱引⽤可以和⼀个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加⼊到与之关联的引用队列中。
1

4、虚引用(PhantomReference)

例:

Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj);
12
虚引用在任何时候都可能被垃圾回收器回收,主要用来跟踪对象被垃圾回收器回收的活动,被回收时会收到⼀个系统通知。虚引用与软引用和弱引用的⼀个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收⼀个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加⼊到与之关联的引用队列中。
1

参考:

https://www.jianshu.com/p/802563da6c3a

https://www.jianshu.com/p/d275812816e5

弱引用:https://www.qycn.com/xzx/article/13116.html