Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Java

ตัวอย่าง Soft Reference และ Phantom Reference ใน Java

Soft Reference - ใช้สำหรับแคชที่คำนึงถึงหน่วยความจำ

Soft Reference เหมาะสำหรับการสร้างแคชที่สามารถปล่อยหน่วยความจำได้เมื่อ JVM ต้องการพื้นที่

ตัวอย่างโค้ด

import java.lang.ref.SoftReference;

class Demo {
    public void displayMsg() {
        System.out.println("Hello there");
    }
}

public class DemoExample {
    public static void main(String[] args) {
        Demo myInstance = new Demo();
        myInstance.displayMsg();
        
        SoftReference mySoftRef = new SoftReference<>(myInstance);
        myInstance = null; // ตัด reference ปกติออก
        
        myInstance = mySoftRef.get(); // ดึงคืนผ่าน soft reference
        if (myInstance != null) {
            myInstance.displayMsg();
        } else {
            System.out.println("Object ถูก garbage collect แล้ว");
        }
    }
}

ผลลัพธ์

Hello there
Hello there

คำอธิบาย: สร้างอ็อบเจกต์ Demo เรียกเมธอด แล้วห่อด้วย SoftReference ตั้งค่า reference ต้นฉบับเป็น null แล้วดึงคืนผ่าน get() ถ้ายังไม่ถูก GC จะได้อ็อบเจกต์กลับมา

Phantom Reference - ใช้สำหรับการทำความสะอาดก่อนทำลาย (pre-mortem cleanup)

Phantom Reference ให้ความยืดหยุ่นมากกว่า finalize() สำหรับจัดการทรัพยากรก่อนที่อ็อบเจกต์จะถูกทำลายจริงๆ

ตัวอย่างโค้ด

import java.lang.ref.*;

class Demo {
    public void displayMsg() {
        System.out.println("Hello there");
    }
}

public class DemoExample {
    public static void main(String[] args) {
        Demo myInstance = new Demo();
        myInstance.displayMsg();
        
        ReferenceQueue refQueue = new ReferenceQueue<>();
        PhantomReference phantomRef = new PhantomReference<>(myInstance, refQueue);
        
        myInstance = null; // ตัด reference ออก
        System.gc(); // ขอให้ GC ทำงาน
        
        // phantomRef.get() จะคืนค่า null เสมอ
        Demo retrieved = phantomRef.get();
        if (retrieved != null) {
            retrieved.displayMsg();
        } else {
            System.out.println("Phantom reference get() คืนค่า null เสมอ");
        }
        
        // รอใน ReferenceQueue เพื่อทำ cleanup
        try {
            Reference ref = refQueue.remove(1000);
            if (ref != null) {
                System.out.println("ทำ cleanup actions ที่นี่");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

ผลลัพธ์

Hello there
Phantom reference get() คืนค่า null เสมอ
ทำ cleanup actions ที่นี่

คำอธิบาย: PhantomReference.get() คืนค่า null เสมอ ไม่สามารถดึงอ็อบเจกต์กลับมาได้ ใช้ร่วมกับ ReferenceQueue เพื่อรับทราบเมื่ออ็อบเจกต์จะถูกทำลาย แล้วจึงดำเนินการ cleanup

ความแตกต่างสำคัญ: Soft reference ยังดึงอ็อบเจกต์กลับมาได้ (ถ้ายังไม่ถูก GC) แต่ Phantom reference ดึงไม่ได้ ต้องใช้ queue แจ้งเตือนแทน