CodeGym /Blog Jawa /Acak /Referensi Phantom ing Jawa
John Squirrels
tingkat
San Francisco

Referensi Phantom ing Jawa

Diterbitake ing grup
Hi! Ing dhiskusi dina iki, kita bakal ngomong kanthi rinci babagan "referensi phantom" (PhantomReference) ing basa Jawa. Apa jenis referensi iki? Apa sebabe diarani "referensi hantu"? Carane padha digunakake? Minangka sampeyan bakal kelingan, Jawa nduweni 4 jinis referensi:
  1. StrongReference (referensi biasa sing digawe nalika nggawe obyek):

    Cat cat = new Cat()

    Ing conto iki, kucing minangka referensi sing kuat.

  2. SoftReference (referensi alus). Kita duwe pelajaran babagan referensi kasebut.

  3. WeakReference (referensi lemah). Ana uga piwulang bab wong-wong mau ing kene .

  4. PhantomReference (referensi phantom).

Telu pungkasan yaiku jinis umum kanthi paramèter jinis (contone, SoftReference<Integer> , WeakReference<MyClass> ). Kelas SoftReference , WeakReference , lan PhantomReference diturunake saka kelas Reference . Cara sing paling penting nalika nggarap kelas kasebut yaiku:
  • njaluk () - ngasilake obyek sing dirujuk;

  • clear () - mbusak referensi kanggo obyek.

Sampeyan ngelingi metode kasebut saka piwulang babagan SoftReference lan WeakReference . Penting kanggo elinga yen padha bisa digunakake kanthi beda karo macem-macem referensi. Dina iki kita ora bakal nyilem menyang telung jinis pisanan. Nanging, kita bakal ngomong babagan referensi phantom. Kita bakal ndemek jinis referensi liyane, nanging mung babagan kepiye bedane karo referensi phantom. Ayo budal! :) Kanggo miwiti, kenapa kita butuh referensi phantom? Kaya sing sampeyan ngerteni, kolektor sampah (gc) ngeculake memori sing digunakake dening obyek Jawa sing ora perlu. Penagih mbusak obyek ing rong "liwat". Ing pass pisanan, mung katon ing obyek, lan, yen perlu, menehi tandha minangka "ora perlu" (tegese, "kanggo dibusak"). Yen ingfinalize()cara wis ditindhes kanggo obyek kasebut, diarani. Utawa bisa uga ora disebut - kabeh gumantung mung apa sampeyan begja. Sampeyan mbokmenawa ngelingi sing finalize()fickle :) Ing pass kapindho kolektor sampah, obyek dibusak lan memori dibebaske. Kelakuane tukang sampah sing ora bisa ditebak nggawe sawetara masalah kanggo kita. Kita ora ngerti persis kapan tukang sampah bakal mbukak. Kita ora ngerti apa finalize()cara kasebut bakal diarani. Kajaba iku, referensi sing kuat kanggo obyek bisa digawe nalika finalize()metode kasebut dieksekusi, saengga obyek kasebut ora bakal dibusak. Kanggo program sing nggawe panjaluk abot ing memori kasedhiya, iki bisa gampang mimpin kanggo OutOfMemoryError. Kabeh iki nyurung kita nggunakake referensi phantom. Kasunyatane iki ngganti prilaku tukang sampah. Yen obyek mung nduweni referensi phantom, banjur:
  • metode finalize () diarani (yen ditimpa)

  • yen ora ana owah-owahan sawise finalize () cara rampung lan obyek isih bisa dibusak, banjur referensi phantom kanggo obyek diselehake ing antrian khusus: ReferenceQueue .

Ingkang paling penting kanggo mangerteni nalika nggarap referensi phantom yaiku obyek kasebut ora dibusak saka memori nganti referensi phantom ana ing antrian iki. Iku bakal dibusak mung sawise cetha () cara disebut ing referensi phantom. Ayo katon ing conto. Pisanan, kita bakal nggawe kelas tes sing bakal nyimpen sawetara jinis data.

public class TestClass {
   private StringBuffer data;
   public TestClass() {
       this.data = new StringBuffer();
       for (long i = 0; i < 50000000; i++) {
           this.data.append('x');
       }
   }
   @Override
   protected void finalize() {
       System.out.println("The finalize method has been called on the TestClass object");
   }
}
Nalika nggawe obyek, kita bakal sengaja menehi "muatan" sing akeh banget (kanthi nambahake 50 yuta karakter "x" kanggo saben obyek) supaya bisa njupuk memori luwih akeh. Kajaba iku, kita ngalahake cara finalize () kanggo ndeleng sing mbukak. Sabanjure, kita butuh kelas sing bakal diwenehi warisan saka PhantomReference . Napa kita butuh kelas kaya ngono? Kabeh iku langsung. Iki bakal ngidini kita nambah logika tambahan kanggo cetha () cara kanggo verifikasi sing referensi phantom tenan wis dibusak (sing tegese obyek wis dibusak).

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class MyPhantomReference<TestClass> extends PhantomReference<TestClass> {

   public MyPhantomReference(TestClass obj, ReferenceQueue<TestClass> queue) {

       super(obj, queue);

       Thread thread = new QueueReadingThread<TestClass>(queue);

       thread.start();
   }

   public void cleanup() {
       System.out.println("Cleaning up a phantom reference! Removing an object from memory!");
       clear();
   }
}
Sabanjure, kita butuh benang sing kapisah sing bakal ngenteni pengumpul sampah nindakake tugase, lan pranala hantu bakal katon ing ReferenceQueue kita . Sanalika referensi kasebut rampung ing antrian, metode cleanup () diarani:

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;

public class QueueReadingThread<TestClass> extends Thread {

   private ReferenceQueue<TestClass> referenceQueue;

   public QueueReadingThread(ReferenceQueue<TestClass> referenceQueue) {
       this.referenceQueue = referenceQueue;
   }

   @Override
   public void run() {

       System.out.println("The thread monitoring the queue has started!");
       Reference ref = null;

       // Wait until the references appear in the queue
       while ((ref = referenceQueue.poll()) == null) {

           try {
               Thread.sleep(50);
           }

           catch (InterruptedException e) {
               throw new RuntimeException("Thread " + getName() + " was interrupted!");
           }
       }

       // As soon as a phantom reference appears in the queue, clean it up
       ((MyPhantomReference) ref).cleanup();
   }
}
Lan pungkasanipun, kita kudu utama () cara, kang bakal sijine iku ing kelas Utama kapisah . Ing cara kasebut, kita bakal nggawe obyek TestClass , referensi phantom, lan antrian kanggo referensi phantom. Sawise iku, kita bakal nelpon tukang sampah lan ndeleng apa sing kedadeyan :)

import java.lang.ref.*;

public class Main {

   public static void main(String[] args) throws InterruptedException {
       Thread.sleep(10000);

       ReferenceQueue<TestClass> queue = new ReferenceQueue<>();
       Reference ref = new MyPhantomReference<>(new TestClass(), queue);

       System.out.println("ref = " + ref);

       Thread.sleep(5000);

       System.out.println("Collecting garbage!");

       System.gc();
       Thread.sleep(300);

       System.out.println("ref = " + ref);

       Thread.sleep(5000);

       System.out.println("Collecting garbage!");

       System.gc();
   }
}
Output konsol:

ref = MyPhantomReference@4554617c 
The thread monitoring the queue has started! 
Collecting garbage! 
The finalize method has been called on the TestClass object 
ref = MyPhantomReference@4554617c 
Collecting garbage! 
Cleaning up a phantom reference! 
Removing an object from memory! 
Apa sing kita deleng ing kene? Kabeh kedadeyan kaya sing wis direncanakake! Metode finalize () obyek kita ditimpa lan diarani nalika tukang sampah lagi mlaku. Sabanjure, referensi phantom dilebokake ing ReferenceQueue . Nalika ana, cara sing cetha () diarani (ing ngendi kita disebut ngresiki () kanggo output menyang console). Pungkasan, obyek kasebut dibusak saka memori. Saiki sampeyan ndeleng persis cara kerjane :) Mesthi, sampeyan ora perlu apal kabeh teori babagan referensi phantom. Nanging luwih apik yen sampeyan ngelingi paling ora poin utama. Kaping pisanan, iki minangka referensi sing paling lemah. Padha teka menyang muter mung nalika ora referensi liyane kanggo obyek kiwa. Dhaptar referensi sing diwenehake ing ndhuwur diurutake kanthi urutan mudhun saka sing paling kuat nganti paling lemah: StrongReference -> SoftReference -> WeakReference -> PhantomReference Referensi hantu mlebu perang mung nalika ora ana referensi sing kuwat, alus, utawa lemah kanggo obyek kita: ) Kapindho, cara njaluk () tansah ngasilake null kanggo referensi phantom. Punika conto prasaja ing ngendi kita nggawe telung jinis referensi kanggo telung jinis mobil:

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

public class Main {

   public static void main(String[] args) {

       Sedan sedan = new Sedan();
       HybridAuto hybrid = new HybridAuto();
       F1Car f1car = new F1Car();

       SoftReference<Sedan> softReference = new SoftReference<>(sedan);
       System.out.println(softReference.get());

       WeakReference<HybridAuto> weakReference = new WeakReference<>(hybrid);
       System.out.println(weakReference.get());
      
       ReferenceQueue<F1Car> referenceQueue = new ReferenceQueue<>();

       PhantomReference<F1Car> phantomReference = new PhantomReference<>(f1car, referenceQueue);
       System.out.println(phantomReference.get());

   }
}
Output konsol:

Sedan@4554617c
HybridAuto@74a14482 
null
Cara njaluk () bali obyek tanggung biasa kanggo referensi alus lan ringkih, nanging bali null kanggo referensi phantom. Katelu, referensi phantom utamane digunakake ing prosedur rumit kanggo mbusak obyek saka memori. Mekaten! :) Sing rampung wulangan kita dina iki. Nanging sampeyan ora bisa pindhah adoh ing teori piyambak, dadi wektu kanggo bali menyang mecahaken tugas! :)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION