JavaRush /Блоги Java /Random-TG /PhantomReference дар Java

PhantomReference дар Java

Дар гурӯҳ нашр шудааст
Салом! Дар дарси имрӯза мо дар бораи истинодҳои Phantom дар Java муфассал сӯҳбат хоҳем кард. Инҳо чӣ гуна пайвандҳо ҳастанд, чаро онҳо "фантом" номида мешаванд ва чӣ гуна истифода бурдани онҳо? Тавре ки шумо дар хотир доред, дар Java 4 намуди пайвандҳо мавҷуданд:
  1. StrongReference (истинодҳои муқаррарие, ки мо ҳангоми сохтани an object эҷод мекунем):

    Cat cat = new Cat()

    гурба дар ин мисол истинодҳои қавӣ аст.

  2. SoftReference (истифодаи нарм). Мо дар бораи ин пайвандҳо лекция доштем.

  3. Reference WeakReference (Истиноди заиф). Дар ин чо дар бораи онхо низ лекция хонда шуд .

  4. PhantomReference (истиноди фантом).

Объектҳои се намуди охирин чоп карда мешаванд (масалан, SoftReference<Integer> , WeakReference<MyClass> ). Синфҳо SoftReferenceва WeakReferenceмерос PhantomReferenceаз синф Reference. Усулҳои муҳимтарини кор бо ин синфҳо инҳоянд:
  • get()- an objectеро, ки ин истинод ба он ишора мекунад, бармегардонад;

  • clear()— истинодро ба an object нест мекунад.

Шумо ин усулхоро аз лекцияхо дар бораи SoftReferenceва WeakReference. Дар хотир доштан муҳим аст, ки онҳо бо намудҳои гуногуни пайвандҳо ба таври гуногун кор мекунанд. Имрӯз мо се намуди аввалро ба таври муфассал баррасӣ намекунем, балки дар бораи пайвандҳои фантомӣ сӯҳбат хоҳем кард. Мо инчунин ба дигар намудҳои истинодҳо муроҷиат хоҳем кард, аммо танҳо дар бахше, ки мо дар бораи он ки чӣ гуна истинодҳои фантомӣ аз онҳо фарқ мекунанд, сӯҳбат хоҳем кард. Бирав! :) Биёед аз он оғоз кунем, ки чаро мо ба истинодҳои фантомӣ дар ҷои аввал ниёз дорем. Тавре ки шумо медонед, коллектори ахлот (Garbage Collector ё gc) барои озод кардани хотира аз an objectҳои нолозими Java масъул аст . Коллектор an objectро дар ду «гузар» мебарорад. Дар гузаргоҳи аввал, он танҳо ба an objectҳо назар мекунад ва агар лозим бошад, онҳоро ҳамчун "нодаркор ва ҳазфшуда" қайд мекунад. Агар ин an object усули бекоршуда дошта бошад finalize(), он номида мешавад. Ё он номида намешавад - вобаста ба барори шумо. Шояд шумо дар хотир доред, ки ин finalize()як чизи ғайриоддӣ аст :) Дар гузариши дуюми коллектор an object нест карда мешавад ва хотира озод карда мешавад. Ин рафтори гайричашмдошти хошоктайёркунй дар сари мо як катор душворихоро ба амал меоварад. Мо аниқ намедонем, ки партовгоҳ кай ба кор медарояд. Мо намедонем, ки усул даъват карда мешавад ё не finalize(). Илова бар ин, ҳангоми кор finalize()пайванди қавӣ ба an object эҷод кардан мумкин аст ва он гоҳ он тамоман нест карда намешавад. Дар системаҳои аз хотира гурусна, ин метавонад ба осонӣ ба OutOfMemoryError. Ҳамаи ин моро ба истифодаи истинодҳои фантомӣ водор мекунад . Гап дар сари он аст, ки ин рафтори ахлотчинро тагьир медихад. Агар ба an object танҳо пайвандҳои фантомӣ боқӣ монанд, пас он дорои:
  • усул номида мешавад finalize()(агар он аз байн рафта бошад);

  • агар пас аз кор finalize()чизе тагйир наёфта бошад ва an objectро хануз нест кардан мумкин бошад, истинод ба an object дар навбати махсус гузошта мешавад - ReferenceQueue.

Муҳимтарин чизе, ки ҳангоми кор бо истинодҳои фантомӣ фаҳмида мешавад, ин аст, ки an object аз хотира хориҷ карда намешавад, то даме ки истинодҳои фантомии он дар ин навбат бошад . Он танҳо пас аз истиноди фантомӣ нест карда мешавад clear(). Биёед як мисолро дида бароем. Аввалан, биёед синфи санҷиширо эҷод кунем, ки баъзе маълумотҳоро нигоҳ медорад.
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!!!");
   }
}
Мо дидаю дониста an objectҳоро ҳангоми сохтани онҳо бо маълумот "бор" мекунем (илова ба ҳар як an object 50 миллион аломати "x") барои гирифтани хотираи бештар. Илова бар ин, мо махсусан усулро бекор мекунем finalize(), то бубинем, ки он кор кардааст. Минбаъд ба мо синфе лозим аст, ки аз PhantomReference. Чаро ба мо чунин синф лозим аст? Ин оддӣ аст. Бо ин роҳ, мо метавонем ба усул мантиқи иловагӣ илова кунем clear(), то бубинем, ки истинодҳои фантомӣ воқеан тоза карда шудаанд (ва аз ин рӯ an object нест карда шудааст).
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();
   }
}
Минбаъд, ба мо як риштаи алоҳида лозим мешавад, ки интизори коллектори ахлот корашро иҷро мекунад ва ReferenceQueueдар навбати мо пайвандҳои фантомӣ пайдо мешаванд. Ҳамин ки чунин пайванд ба навбат ворид мешавад, усули он даъват мешавад 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();
   }
}
Ва ниҳоят, ба мо усул лозим аст main(): биёед онро дар як синфи алоҳида ҷойгир кунем Main. Дар он мо an object TestClass, истинод ба он фантом ва навбат барои истинодҳои фантомӣ эҷод мекунем. Пас аз он мо ба ҷамъкунандаи ахлот занг мезанем ва бубинем, ки чӣ мешавад :)
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();
   }
}
Натиҷаи консол: ref = MyPhantomReference@4554617c Мониторинги навбат оғоз шуд! Ҷамъоварии ахлот даъват карда мешавад! Усули ниҳоӣ дар an objectи TestClass даъват карда шуд!!! ref = MyPhantomReference@4554617c Ҷамъоварии ахлот даъват карда мешавад! Тоза кардани пайванди фантом! Хориҷ кардани an object аз хотира! Мо дар ин ҷо чӣ мебинем? Ҳама чиз тавре рӯй дод, ки мо нақша доштем! Синфи an objectи мо методи бекоршуда дошт finalize()ва он ҳангоми кор кардани коллектор даъват карда мешуд. Баъдан, пайванди фантомӣ дар навбат гузошта шуд ReferenceQueue. Дар он ҷо вай усуле дошт clear()(аз он мо cleanup()барои илова кардани натиҷа ба консол кор кардем). Дар натиҷа, an object аз хотира хориҷ карда шуд. Акнун шумо мебинед, ки он чӣ гуна кор мекунад :) Албатта, ба шумо лозим нест, ки тамоми назарияи марбут ба истинодҳои фантомиро аз ёд кунед. Аммо хуб мешавад, агар шумо ақаллан нуктаҳои асосиро дар хотир доред. Аввалан , инҳо заифтарин пайвандҳо мебошанд. Онҳо танҳо вақте ба кор медароянд, ки ягон истинод ба an objectи дигар вуҷуд надошта бошад. Рӯйхати истинодҳое, ки мо дар боло додаем, бо тартиби камшавии қувват аст: StrongReference-> SoftReference-> WeakReference-> PhantomReference Пайванди фантомӣ танҳо вақте ба ҷанг дохил мешавад, ки дар an objectи мо ягон пайванди қавӣ, нарм ё заиф вуҷуд надошта бошад :) Дуюм , усул get()барои пайванди фантомӣ ҳамеша бармегардад null. Ин як мисоли оддӣ аст, ки мо барои се намуди гуногуни мошинҳо се намуди истинодҳо эҷод мекунем:
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());

   }
}
Натиҷаи консол: Sedan@4554617c HybridAuto@74a14482 null Ин усул get()an objectҳои хеле муқаррариро барои пайванди нарм ва пайванди заиф баргардонд, аммо nullбарои як фантом баргашт. Сеюм , самти асосии истифодаи истинодҳои фантомӣ расмиёти мураккаби хориҷ кардани an objectҳо аз хотира мебошад. Ҳамааш ҳамин! :) Ин дарси имрӯзаи моро ба анҷом мерасонад. Аммо танҳо назария шуморо дур карда наметавонад, бинобар ин вақти он расидааст, ки ба ҳалли мушкилот баргардед! :)
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION