2015-11-02 2 views
7

प्रेत संदर्भ के बारे में बहुत कुछ पता चला लेकिन इसके व्यावहारिक उपयोग को खोजने में असमर्थ। और तार्किक बात() विधि प्रेत संदर्भप्रेत संदर्भों का व्यावहारिक उपयोग क्या है - जावा?

के मामले में अशक्त रिटर्न

उत्तर

6

आप इस blog का पालन कर सकते हैं:

क्या अच्छा PhantomReferences कर रहे हैं? मुझे केवल उनके लिए दो गंभीर मामलों के बारे में पता है: सबसे पहले, वे आपको यह निर्धारित करने की अनुमति देते हैं कि ऑब्जेक्ट को स्मृति से हटा दिया गया था। वे वास्तव में निर्धारित करने का एकमात्र तरीका हैं। यह आम तौर पर है कि उपयोगी नहीं है, लेकिन जोड़ तोड़ बड़ी छवियों की तरह कुछ बहुत ही विशेष परिस्थितियों में उपयोगी हो सकता है: यदि आप यह सुनिश्चित करें कि एक छवि कचरा एकत्र किया जाना चाहिए के लिए पता है, तुम जब तक यह वास्तव में लोड प्रयास करने से पहले है इंतजार कर सकते हैं करने के लिए अगली छवि, और इसलिए डरावनी आउटऑफमेमरी एरर कम संभावना बनाते हैं।

दूसरा, PhantomReferences को अंतिम रूप देने के साथ एक मौलिक समस्या से बचने के: को अंतिम रूप देने() पद्धतियों उन्हें नई मजबूत संदर्भ बनाने के द्वारा "को फिर से शुरू" कर सकते हैं वस्तुओं। तो तुमने क्या कहा? ठीक है, समस्या है कि एक वस्तु जो अंतिम रूप देने को ओवरराइड करता है() अब करने के क्रम में कम से कम दो अलग कचरा संग्रहण चक्र में कचरा होने के लिए एकत्र किया जा निर्धारित किया जाना चाहिए। जब पहला चक्र निर्धारित करता है कि यह कचरा है, तो यह अंतिमकरण के लिए योग्य हो जाता है। (स्लिम, लेकिन दुर्भाग्य से वास्तविक) संभावना गया था कि वस्तु "पुनर्जीवित" की वजह से अंतिम रूप दिए जाने के दौरान, कचरा कलेक्टर वस्तु वास्तव में हटाया जा सकता है पहले फिर से चलाने के लिए है। और क्योंकि अंतिमकरण समय-समय पर नहीं हुआ है, कचरे की मनमानी संख्या संग्रह चक्र हो सकता है जबकि ऑब्जेक्ट अंतिमकरण की प्रतीक्षा कर रहा था। इसका अर्थ यह है कि कचरा वस्तुओं को वास्तव में साफ करने में गंभीर देरी हो सकती है, और यही कारण है कि आप अधिकतर ढेर कचरा होने पर भी आउटऑफमेमरी एरर प्राप्त कर सकते हैं।

भी पढ़ें: The Mysterious Phantom Reference

निम्नलिखित कोड पर विचार करें।

public class Foo { 

    private String bar; 

    public Foo(String bar) { 
     this.bar = bar; 
    } 

    public String foo() { 
     return bar; 
    } 
} 

तो देता है के बाद वस्तु पूरी तरह से आवेदन कुछ करने के लिए मैं चाहता हूँ द्वारा dereferenced कर दिया गया है कहते हैं कि कैसे foo फोन()। यहां कुछ कोड दिया गया है कि मैं काम करने की उम्मीद करता हूं जो इसे एक निगल के साथ करेगा।

// initialize 
ReferenceQueue<Foo> queue = new ReferenceQueue<Foo>(); 
ArrayList< PhantomReference<Foo>> list=new ArrayList<PhantomReference<Foo>>(); 

for (int i = 0; i < 10; i++) { 
    Foo o = new Foo(Integer.toOctalString(i)); 
    list.add(new PhantomReference<Foo>(o, queue)); 
} 

// make sure the garbage collector does it’s magic 
System.gc(); 

// lets see what we’ve got 
Reference<? extends Foo> referenceFromQueue; 
for (PhantomReference<Foo> reference : list) 
    System.out.println(reference.isEnqueued()); 

while ((referenceFromQueue = queue.poll()) != null) { 
    System.out.println(referenceFromQueue.get()); 
    referenceFromQueue.clear(); 
} 

फ़ैंटॉम रेफरेंस फू और संदर्भक्यू का उदाहरण लेता है। चूंकि फू को कोई हैंडल नहीं रखा जाता है, यह तुरंत मर जाना चाहिए। इसके बाद, वीएम को इकट्ठा करने के लिए बताएं क्योंकि इसमें संग्रह स्वाभाविक रूप से ट्रिगर करने के लिए ढेर में पर्याप्त नहीं है। पहली बात यह है कि मैं से पूछने जा रहा हूं फ़ैंटॉम रेफरेंस है; क्या आपको लगाया गया है इस मामले में उत्तर सत्य होगा। इसके बाद मैं संदर्भ के लिए कतार पूछता हूं लेकिन जैसा कि आप देख सकते हैं, कॉलिंग() हमेशा शून्य लौटाती है। एकमात्र समाधान के बारे में का अर्थ उन संसाधनों या वस्तुओं को लपेटना है जिन्हें आप पर फ़ैंटॉम रेफरेंस के उप-वर्ग में इंटरैक्ट करना चाहते थे।

public class FinalizeStuff<Foo> extends PhantomReference<Foo> { 

    public FinalizeStuff(Foo foo, ReferenceQueue<? super Foo> queue) { 
     super(foo, queue); 
    } 

    public void bar() { 
     System.out.println("foobar is finalizing resources"); 
    } 
} 

इस मामले में मैं PhantomReference की भावना का उल्लंघन करने लगते हैं कि होगा के रूप में उपवर्ग में फू रैप करने के लिए नहीं जा रहा हूँ। इसके बजाय मैं फू से जुड़े संसाधनों को लपेट रहा हूं और उनके साथ बातचीत कर रहा हूं। अब मैं कर सकता हूं।

// initialize 
ReferenceQueue<Foo> queue = new ReferenceQueue<Foo>(); 
ArrayList< FinalizeStuff<Foo>> list = new ArrayList<FinalizeStuff<Foo>>(); 
ArrayList<Foo> foobar = new ArrayList<Foo>(); 

for (int i = 0; i < 10; i++) { 
    Foo o = new Foo(Integer.toOctalString(i)); 
    foobar.add(o); 
    list.add(new FinalizeStuff<Foo>(o, queue)); 
} 

// release all references to Foo and make sure the garbage collector does it’s magic 
foobar = null; 
System.gc(); 

// should be enqueued 
Reference<? extends Foo> referenceFromQueue; 
for (PhantomReference<Foo> reference : list) { 
    System.out.println(reference.isEnqueued()); 
} 

// now we can call bar to do what ever it is we need done 
while ((referenceFromQueue = queue.poll()) != null) { 
    ((FinalizeStuff)referenceFromQueue).bar(); 
    referenceFromQueue.clear(); 
} 
संबंधित मुद्दे