JavaRush /Blog Jawa /Random-JV /PhantomReference ing Jawa

PhantomReference ing Jawa

Diterbitake ing grup
Hello! Ing wulangan dina iki, kita bakal ngomong kanthi rinci babagan Referensi Phantom ing basa Jawa. Tautan apa iki, kenapa diarani "phantom" lan kepiye cara nggunakake? Nalika sampeyan ngelingi, ana 4 jinis pranala ing Jawa:
  1. StrongReference (referensi biasa sing digawe nalika nggawe obyek):

    Cat cat = new Cat()

    kucing ing conto iki minangka referensi Kuwat.

  2. SoftReference (referensi alus). Kita duwe kuliah babagan pranala kasebut.

  3. WeakReference (referensi lemah). Ana ceramah bab wong-wong mau uga, kene .

  4. PhantomReference (referensi phantom).

Obyek saka telung jinis pungkasan diketik (contone, SoftReference<Integer> , WeakReference<MyClass> ). Kelas SoftReference, WeakReferencelan PhantomReferencewarisan saka kelas Reference. Cara sing paling penting nalika nggarap kelas kasebut yaiku:
  • get()- ngasilake obyek link iki nuduhake;

  • clear()- mbusak referensi kanggo obyek.

Sampeyan ngelingi cara iki saka ceramah babagan SoftReferencelan WeakReference. Iku penting kanggo elinga yen padha bisa beda karo macem-macem jinis pranala. Dina iki kita ora bakal nimbang telung jinis pisanan kanthi rinci, nanging bakal ngomong babagan pranala phantom. Kita uga bakal ndemek jinis pranala liyane, nanging mung ing bagean sing bakal kita pirembagan babagan carane pranala phantom beda-beda. Tindak! :) Ayo dadi miwiti karo apa kita kudu pranala phantom ing Panggonan pisanan. Kaya sing sampeyan ngerteni, pengumpul sampah (Pengumpul Sampah utawa gc) tanggung jawab kanggo mbebasake memori saka 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 lan bakal dibusak." Yen obyek iki wis cara overridden finalize(), diarani. Utawa ora disebut - gumantung ing luck. Sampeyan mbokmenawa ngelingi sing iki finalize()bab fickle :) Ing pass kapindho kolektor, obyek dibusak lan memori dibebaske. Prilaku pengumpul sampah sing ora bisa ditebak iki nggawe sawetara masalah kanggo kita. Kita ora ngerti persis kapan tukang sampah bakal miwiti kerja. Kita ora ngerti apa cara kasebut bakal diarani finalize(). Kajaba iku, sajrone operasi, finalize()tautan sing kuat menyang obyek bisa digawe, banjur ora bakal dibusak. Ing sistem memori-luwe, iki bisa gampang mimpin kanggo OutOfMemoryError. Kabeh iki nyurung kita nggunakake pranala phantom . Intine iki ngubah tingkah lakune tukang sampah. Yen mung ana pranala phantom sing ditinggalake menyang obyek kasebut, mula ana:
  • cara diarani finalize()(yen ditimpa);

  • yen sawise karya finalize()ora diganti lan obyek isih bisa dibusak, referensi phantom kanggo obyek diselehake ing antrian khusus - ReferenceQueue.

Bab sing paling penting kanggo dimangerteni nalika nggarap referensi phantom yaiku obyek ora dicopot saka memori anggere referensi phantom ana ing antrian iki . Iku bakal dibusak mung sawise link phantom kang clear(). Ayo katon ing conto. Pisanan, ayo nggawe kelas tes sing bakal nyimpen sawetara 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("У an object TestClass вызван метод finalize!!!");
   }
}
Kita sengaja "muat" obyek karo data nalika nggawe (nambah 50 yuta "x" karakter kanggo saben obyek) kanggo njupuk munggah memori liyane. Kajaba iku, kita khusus ngatasi cara kasebut finalize()kanggo ndeleng manawa bisa digunakake. Sabanjure kita butuh kelas sing bakal dadi warisan saka PhantomReference. Napa kita butuh kelas sing kaya ngono? Iku prasaja. Kanthi cara iki kita bisa nambah logika tambahan kanggo cara clear()kanggo ndeleng sing referensi phantom bener wis dibusak (lan mulane 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("Очистка фантомной ссылки! Удаление an object из памяти!");
       clear();
   }
}
Sabanjure, kita butuh benang sing kapisah sing bakal ngenteni pengumpul sampah kanggo nindakake, lan ReferenceQueuetautan phantom bakal katon ing antrian kita. Sanalika link kasebut mlebu ing antrian, metode kasebut bakal diarani cleanup():
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("Поток, отслеживающий очередь, стартовал!");
       Reference ref = null;

       //ждем, пока в очереди появятся ссылки
       while ((ref = referenceQueue.poll()) == null) {

           try {
               Thread.sleep(50);
           }

           catch (InterruptedException e) {
               throw new RuntimeException("Поток " + getName() + " был прерван!");
           }
       }

       //How только в очереди появилась фантомная link - очистить ее
       ((MyPhantomReference) ref).cleanup();
   }
}
Lan pungkasane, kita butuh metode main(): ayo dilebokake ing kelas sing kapisah Main. Ing kono 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("Вызывается сборка мусора!");

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

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

       Thread.sleep(5000);

       System.out.println("Вызывается сборка мусора!");

       System.gc();
   }
}
Output konsol: ref = MyPhantomReference@4554617c Utas ngawasi antrian wis diwiwiti! Ngumpulake sampah diarani! Metode finalisasi wis diarani obyek TestClass !!! ref = MyPhantomReference@4554617c Koleksi sampah diarani! Ngresiki link phantom! Mbusak obyek saka memori! Apa sing kita deleng ing kene? Kabeh kedadeyan kaya sing wis direncanakake! Kelas obyek kita duwe metode sing diganti finalize()lan diarani nalika kolektor lagi mlaku. Sabanjure, link phantom wis antri ReferenceQueue. Ing kana dheweke duwe metode sing diarani clear()(saka sing kita lakoni cleanup()kanggo nambah output menyang konsol). Akibaté, obyek wis dibusak saka memori. Saiki sampeyan ndeleng persis cara kerjane :) Mesthi wae, sampeyan ora perlu ngapalake kabeh teori sing ana gandhengane karo tautan phantom. Nanging bakal apik yen sampeyan ngelingi paling ora poin utama. Kaping pisanan , iki minangka tautan sing paling lemah. Padha teka menyang muter mung nalika ora ana referensi liyane kanggo obyek. Dhaptar pranala sing wis diwenehake ing ndhuwur ana ing urutan mudhun kekuatan: StrongReference-> SoftReference-> WeakReference-> PhantomReference Link hantu bakal mlebu perang mung yen ora ana pranala Strong, Soft, utawa Weak kanggo obyek kita :) Kapindho , metode get()kanggo link phantom tansah bali null. Iki conto prasaja sing nggawe telung jinis tautan 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 get()ngasilake obyek sing cukup normal kanggo link alus lan link sing ringkih, nanging bali nullmenyang phantom. Katelu , area utama panggunaan referensi phantom yaiku prosedur rumit kanggo mbusak obyek saka memori. Iku kabeh! :) Iki rampung pelajaran kita kanggo dina iki. Nanging teori mung ora bakal nggawa sampeyan adoh, dadi wektune bali kanggo ngrampungake masalah! :)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION