Java中的引用

qq_42687144發表於2020-11-15

java中的強引用

略就是普通的new物件

java中的軟引用

使用SoftReference建立一個軟引用物件,

當java的記憶體不足時,垃圾回收器會幹掉軟引用

軟引用非常適合快取使用

/**
 * @version: JavaEE
 * @description: java中的軟引用
 * @author: Mr.xzx
 * @create: 2020-11-03 18:16
 * @version:1.0
 **/
public class SoftReferenceTest {
    public static void main(String[] args) {
        SoftReference<byte[]> m = new SoftReference<>(new byte[1024 * 1024 * 10]);
        System.out.println(m.get());
        System.gc();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(m.get());
        //再分配一個陣列,heap將裝不下,這時候系統會回收垃圾,先回收一次,如果不夠,會把軟引用幹掉
        byte[] b = new byte[1024 * 1024 * 15];
        System.out.println(m.get());
    }
}

java中的弱引用

垃圾回收器看到弱引用就會幹掉弱引用

/**
 * @version: JavaEE
 * @description: java中的弱引用
 * @author: Mr.xzx
 * @create: 2020-11-03 18:43
 * @version:1.0
 **/
public class WeakReferenceTest {
    public static void main(String[] args) {
        WeakReference<M> m = new WeakReference<>(new M());
        System.out.println(m.get());
        System.gc();
        System.out.println(m.get());
    }
}

java中的虛引用

無論什麼時候都get()不到該物件的引用

一個虛引用物件,要被回收時,垃圾回收器,會將它扔進一個佇列(引用佇列)中,如果引用佇列中有該物件了,那麼直接將這個虛引用物件直接回收

虛引用最大的作用是管理直接記憶體(堆外記憶體),實現零拷貝

public class PhantomReferenceTest {
    private static final List<Object> list = new LinkedList<>();
    private static final ReferenceQueue<M> QUEUE = new ReferenceQueue<>();
    public static void main(String[] args) {
        PhantomReference<M> phantomReference = new PhantomReference<>(new M(), QUEUE);
        System.out.println(phantomReference.get());
    }
}

java中軟引用的體現

ThreadLocal的講解

public class ThreadLocalTest {
    static ThreadLocal<M> tl = new ThreadLocal<>();

    public static void main(String[] args) {
        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(tl.get());
        }).start();
        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            tl.set(new M());
             //tl.remove();如果tl不使用了,要呼叫remove方法,不然會存在記憶體洩漏(oom:記憶體溢位)
        }).start();
    }
}

threadLocal建立一個執行緒容器, 1號執行緒等待2秒,2號執行緒1秒就向容器中新增了一個M物件,但是1號執行緒2秒後依然無法get()到為null

所謂向ThreadLocal中set值,就是向當前執行緒Thread中的(父類成員變數)threadlocals的map中設定鍵值對,鍵是ThreadLocal本身,值是物件M();形成一個鍵值對Entry

這個鍵值對entry是繼承了WeakReference弱引用
在這裡插入圖片描述

面試會問:執行緒池慎用ThreadLocal, 當我拿出一個執行緒,在他的map中新增了一些ThreadLocal的鍵值對,使用結束後也沒有進行remove方法,那麼我下次在拿到這個執行緒時,當中還會存在之前遺留的老的值,會出現值錯亂等

相關文章