John Squirrels
స్థాయి
San Francisco

జావాలో ఫాంటమ్ సూచనలు

సమూహంలో ప్రచురించబడింది
హాయ్! నేటి చర్చలో, మేము జావాలో "ఫాంటమ్ రిఫరెన్స్" (ఫాంటమ్ రిఫరెన్స్) గురించి వివరంగా మాట్లాడుతాము. ఇవి ఎలాంటి సూచనలు? వాటిని "ఫాంటమ్ రిఫరెన్స్" అని ఎందుకు పిలుస్తారు? అవి ఎలా ఉపయోగించబడతాయి? మీరు గుర్తుచేసుకున్నట్లుగా, జావాలో 4 రకాల సూచనలు ఉన్నాయి:
  1. StrongReference (ఒక వస్తువును సృష్టించేటప్పుడు మనం సృష్టించే సాధారణ సూచనలు):

    Cat cat = new Cat()

    ఈ ఉదాహరణలో, పిల్లి ఒక బలమైన సూచన.

  2. సాఫ్ట్ రిఫరెన్స్ (సాఫ్ట్ రిఫరెన్స్). అటువంటి సూచనల గురించి మాకు పాఠం ఉంది .

  3. బలహీనమైన సూచన (బలహీనమైన సూచన). వాటి గురించి ఇక్కడ ఒక పాఠం కూడా ఉంది .

  4. ఫాంటమ్ రిఫరెన్స్ (ఫాంటమ్ రిఫరెన్స్).

చివరి మూడు టైప్ పారామితులతో కూడిన సాధారణ రకాలు (ఉదాహరణకు, SoftReference<Integer> , WeakReference<MyClass> ). SoftReference , WeakReference , మరియు PhantomReference తరగతులు రిఫరెన్స్ క్లాస్ నుండి వారసత్వంగా పొందబడ్డాయి . ఈ తరగతులతో పనిచేసేటప్పుడు అత్యంత ముఖ్యమైన పద్ధతులు:
  • get() — రిఫరెన్స్ చేయబడిన వస్తువును తిరిగి ఇస్తుంది;

  • clear() — వస్తువుకు సంబంధించిన సూచనను తొలగిస్తుంది.

మీరు SoftReference మరియు WeakReference పాఠాల నుండి ఈ పద్ధతులను గుర్తుంచుకుంటారు . వారు వివిధ రకాల సూచనలతో విభిన్నంగా పని చేస్తారని గుర్తుంచుకోవడం ముఖ్యం. ఈ రోజు మనం మొదటి మూడు రకాలుగా డైవ్ చేయము. బదులుగా, మేము ఫాంటమ్ సూచనల గురించి మాట్లాడుతాము. మేము ఇతర రకాల సూచనలను టచ్ చేస్తాము, కానీ అవి ఫాంటమ్ రిఫరెన్స్‌ల నుండి ఎలా విభిన్నంగా ఉన్నాయి అనేదానికి సంబంధించి మాత్రమే. వెళ్దాం! :) ప్రారంభించడానికి, మనకు ఫాంటమ్ సూచనలు ఎందుకు అవసరం? మీకు తెలిసినట్లుగా, చెత్త కలెక్టర్ (gc) అనవసరమైన జావా వస్తువులు ఉపయోగించిన మెమరీని విడుదల చేస్తుంది. కలెక్టర్ ఒక వస్తువును రెండు "పాస్"లలో తొలగిస్తాడు. మొదటి పాస్‌లో, ఇది వస్తువులను మాత్రమే చూస్తుంది మరియు అవసరమైతే, వాటిని "అనవసరం" (అంటే "తొలగించబడాలి") అని గుర్తు చేస్తుంది. ఉంటేfinalize()వస్తువు కోసం పద్ధతి భర్తీ చేయబడింది, దీనిని అంటారు. లేదా అది పిలవబడకపోవచ్చు - ఇది మీరు అదృష్టవంతులదా అనే దానిపై మాత్రమే ఆధారపడి ఉంటుంది. అది చంచలమైనదని మీకు బహుశా గుర్తుండే ఉంటుంది finalize():) చెత్త సేకరించేవారి రెండవ పాస్‌లో, ఆబ్జెక్ట్ తొలగించబడింది మరియు జ్ఞాపకశక్తి విముక్తమవుతుంది. చెత్త సేకరించేవారి అనూహ్య ప్రవర్తన మాకు అనేక సమస్యలను సృష్టిస్తుంది. చెత్త సేకరించే యంత్రం ఎప్పటి నుంచి పని ప్రారంభిస్తుందో మాకు తెలియదు. finalize()పద్ధతి అని పిలుస్తారో లేదో మాకు తెలియదు . అదనంగా, ఒక వస్తువు యొక్క పద్ధతిని అమలు చేస్తున్నప్పుడు దాని గురించి బలమైన సూచన సృష్టించబడుతుంది finalize(), ఆ సందర్భంలో ఆ వస్తువు పూర్తిగా తొలగించబడదు. అందుబాటులో ఉన్న మెమరీపై భారీ డిమాండ్‌లు చేసే ప్రోగ్రామ్‌ల కోసం, ఇది సులభంగా ఒక OutOfMemoryError. ఇవన్నీ ఫాంటమ్ రిఫరెన్స్‌లను ఉపయోగించడానికి మనల్ని పురికొల్పుతాయి. దీంతో చెత్త సేకరించేవారి తీరు మారుతుందనేది వాస్తవం. వస్తువు కేవలం ఫాంటమ్ రిఫరెన్స్‌లను కలిగి ఉంటే, అప్పుడు:
  • దాని ఖరారు() పద్ధతి అంటారు (అది ఓవర్‌రైడ్ చేయబడితే)

  • ఫైనలైజ్() పద్ధతి పూర్తయిన తర్వాత ఏమీ మారకపోతే మరియు ఆబ్జెక్ట్ ఇప్పటికీ తొలగించబడితే, ఆబ్జెక్ట్‌కు సంబంధించిన ఫాంటమ్ రిఫరెన్స్ ప్రత్యేక క్యూలో ఉంచబడుతుంది: రిఫరెన్స్ క్యూ .

ఫాంటమ్ రిఫరెన్స్‌లతో పని చేస్తున్నప్పుడు అర్థం చేసుకోవలసిన ముఖ్యమైన విషయం ఏమిటంటే, ఆబ్జెక్ట్ దాని ఫాంటమ్ రిఫరెన్స్ ఈ క్యూలో ఉండే వరకు మెమరీ నుండి తొలగించబడదు. ఫాంటమ్ రిఫరెన్స్‌లో స్పష్టమైన() పద్ధతిని పిలిచిన తర్వాత మాత్రమే ఇది తొలగించబడుతుంది . ఒక ఉదాహరణ చూద్దాం. ముందుగా, మేము ఒక రకమైన డేటాను నిల్వ చేసే పరీక్ష తరగతిని సృష్టిస్తాము.
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");
   }
}
మేము ఆబ్జెక్ట్‌లను సృష్టించినప్పుడు, ఎక్కువ మెమరీని తీసుకోవడానికి ఉద్దేశపూర్వకంగా వాటికి భారీ "లోడ్" (ప్రతి వస్తువుకు 50 మిలియన్ "x" అక్షరాలను జోడించడం ద్వారా) అందిస్తాము. అదనంగా, మేము అది అమలు చేయబడిందో లేదో చూడటానికి ఫైనల్() పద్ధతిని భర్తీ చేస్తాము. తరువాత, మనకు ఫాంటమ్ రిఫరెన్స్ నుండి వారసత్వంగా వచ్చే తరగతి అవసరం . మనకు అలాంటి తరగతి ఎందుకు అవసరం? అంతా సూటిగా ఉంటుంది. ఇది ఫాంటమ్ రిఫరెన్స్ నిజంగా క్లియర్ చేయబడిందని ధృవీకరించడానికి స్పష్టమైన() పద్ధతికి అదనపు లాజిక్‌ను జోడించడానికి మమ్మల్ని అనుమతిస్తుంది (అంటే ఆబ్జెక్ట్ తొలగించబడిందని అర్థం).
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();
   }
}
తర్వాత, చెత్త సేకరించే వ్యక్తి తన పనిని చేయడానికి వేచి ఉండే ప్రత్యేక థ్రెడ్ అవసరం మరియు మా రిఫరెన్స్ క్యూలో ఫాంటమ్ లింక్‌లు కనిపిస్తాయి . అటువంటి సూచన క్యూలో ముగిసిన వెంటనే, క్లీనప్() పద్ధతిని పిలుస్తారు:
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();
   }
}
చివరకు, మనకు ప్రధాన () పద్ధతి అవసరం, దానిని మేము ప్రత్యేక ప్రధాన తరగతిలో ఉంచుతాము . ఆ పద్ధతిలో, మేము టెస్ట్‌క్లాస్ ఆబ్జెక్ట్, దానికి ఫాంటమ్ రిఫరెన్స్ మరియు ఫాంటమ్ రిఫరెన్స్‌ల కోసం క్యూని సృష్టిస్తాము . ఆ తర్వాత, మేము చెత్త సేకరించేవారిని పిలుస్తాము మరియు ఏమి జరుగుతుందో చూద్దాం :)
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();
   }
}
కన్సోల్ అవుట్‌పుట్:
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!
మనం ఇక్కడ ఏమి చూస్తాము? అంతా మనం అనుకున్నట్లే జరిగింది! మా ఆబ్జెక్ట్ యొక్క ఖరారు() పద్ధతి భర్తీ చేయబడింది మరియు చెత్త సేకరించేవాడు నడుస్తున్నప్పుడు దీనిని పిలుస్తారు. తర్వాత, ఫాంటమ్ రిఫరెన్స్ రిఫరెన్స్ క్యూలో ఉంచబడింది . అక్కడ ఉన్నప్పుడు, దాని స్పష్టమైన() పద్ధతిని పిలుస్తారు (దీనిలో మేము కన్సోల్‌కు అవుట్‌పుట్ చేయడానికి క్లీనప్() అని పిలుస్తాము). చివరగా, ఆబ్జెక్ట్ మెమరీ నుండి తొలగించబడింది. ఇది ఎలా పని చేస్తుందో ఇప్పుడు మీరు చూస్తారు :) వాస్తవానికి, ఫాంటమ్ రిఫరెన్స్‌ల గురించి మీరు అన్ని సిద్ధాంతాలను గుర్తుంచుకోవలసిన అవసరం లేదు. అయితే కనీసం ముఖ్యాంశాలైనా గుర్తుంచుకుంటే బాగుంటుంది. మొదటిది, ఇవి అన్నింటికంటే బలహీనమైన సూచనలు. వస్తువుకు సంబంధించి ఇతర సూచనలు లేనప్పుడు మాత్రమే అవి అమలులోకి వస్తాయి. మేము పైన ఇచ్చిన సూచనల జాబితా బలమైన నుండి బలహీనమైన వాటికి అవరోహణ క్రమంలో క్రమబద్ధీకరించబడింది: StrongReference -> SoftReference -> WeakReference -> PhantomReference మా వస్తువుకు బలమైన, మృదువైన లేదా బలహీనమైన సూచనలు లేనప్పుడు మాత్రమే ఫాంటమ్ రిఫరెన్స్ యుద్ధంలోకి ప్రవేశిస్తుంది: ) రెండవది, ఫాంటమ్ సూచన కోసం get() పద్ధతి ఎల్లప్పుడూ శూన్యాన్ని అందిస్తుంది . ఇక్కడ మేము మూడు రకాల కార్ల కోసం మూడు విభిన్న రకాల సూచనలను సృష్టించే ఒక సాధారణ ఉదాహరణ:
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 () పద్ధతి మృదువైన మరియు బలహీనమైన సూచనల కోసం పూర్తిగా సాధారణ వస్తువులను అందించింది, అయితే ఇది ఫాంటమ్ సూచన కోసం శూన్యతను అందించింది. మూడవది, ఫాంటమ్ సూచనలు ప్రధానంగా మెమరీ నుండి వస్తువులను తొలగించడానికి సంక్లిష్టమైన విధానాలలో ఉపయోగించబడతాయి. అంతే! :) అది ఈ రోజు మన పాఠాన్ని ముగించింది. కానీ మీరు ఒంటరిగా సిద్ధాంతంపై ఎక్కువ దూరం వెళ్లలేరు, కాబట్టి ఇది పనులను పరిష్కరించడానికి తిరిగి రావడానికి సమయం! :)
వ్యాఖ్యలు
  • జనాదరణ పొందినది
  • కొత్తది
  • పాతది
వ్యాఖ్యానించడానికి మీరు తప్పనిసరిగా సైన్ ఇన్ చేసి ఉండాలి
ఈ పేజీకి ఇంకా ఎలాంటి వ్యాఖ్యలు లేవు