2015-02-04 28 views
6

जावा एपीआई डॉक से:जब जावा में धागा स्मृति से हटा दिया जाता है?

सभी थ्रेड कि डेमॉन धागे मौत हो चुकी है नहीं कर रहे हैं, या तो करने के लिए कॉल से वापस लौट कर:

जावा वर्चुअल मशीन जब तक निम्नलिखित होता धागे पर अमल करने के लिए जारी रन विधि या अपवाद फेंककर रन विधि से परे प्रचारित करता है।

मुझे आशा है कि मेरी धारणा सही है कि एक बार थ्रेड run() विधि को समाप्त कर देता है, यह कचरा संग्रह के लिए योग्य हो जाता है। एक है कि ऐसा करने के लिए null करने के लिए अपने संदर्भ के लिए सेट करना चाहिए run() से लौटने के बाद

  1. यदि यह कचरा संग्रहण के लिए पात्र नहीं बन जाता है: एक ही संदर्भ में मैं बस के बारे में जानने के लिए उत्सुक हूँ?
  2. कचरा संग्रह के लिए योग्य होने का मतलब यह नहीं है कि ऑब्जेक्ट स्मृति से हटा दिया जाएगा। अंतर्निहित ऑपरेटिंग सिस्टम/जेवीएम के कचरे के एकत्र होने पर यह विवेकाधिकार पर है। लेकिन कोई कैसे सुनिश्चित कर सकता है (या तो जावा प्रोग्राम या बाहरी उपकरण के माध्यम से) कि ऑब्जेक्ट मेमोरी से पूरी तरह से हटा दिया गया है?
  3. यदि एक थ्रेड कहा जाता है कि यह एक रन() विधि समाप्त हो जाने के बाद मृत होता है, तो क्यों मैं isAlive() या getState() को पर समान थ्रेड ऑब्जेक्ट निष्पादित करने में सक्षम हो सकता हूं? दोनों कॉल क्रमश: false और RUNNABLE लौटते हैं।

उत्तर

8

Thread कक्षा वास्तविक धागे के लिए एक प्रॉक्सी है जो मूल स्मृति में है।

मुझे आशा है कि मेरी धारणा सही है कि एक बार धागा अपनी दौड़() विधि को समाप्त कर देता है, यह कचरा संग्रह के लिए योग्य हो जाता है।

वास्तव में रन() के बाद कोड का थोड़ा सा हिस्सा है, यह कोड बेजोड़ अपवादों को संभालता है।

एक बार थ्रेड मरने के बाद इसकी मूल स्मृति और ढेर तुरंत जीसी की आवश्यकता के बिना मुक्त हो जाते हैं। हालांकि, Thread ऑब्जेक्ट किसी अन्य ऑब्जेक्ट की तरह है और यह तब तक रहता है जब तक कि जीसी ने फैसला नहीं किया है कि यह मुफ्त हो सकता है उदा। इसके लिए कोई मजबूत संदर्भ नहीं है।

इसी प्रकार, एक फ़ाइलऑटपुटस्ट्रीम ऑपरेटिंग सिस्टम में एक फ़ाइल के लिए प्रॉक्सी है। फ़ाइल close() या यहां तक ​​कि हटाए जाने के बाद भी आप ऑब्जेक्ट का संदर्भ दे सकते हैं।

यदि यह रन() से लौटने के बाद कचरा संग्रह के लिए योग्य नहीं बनता है, तो क्या इसे करने के लिए इसे संदर्भित करना चाहिए?

आपको शायद ही कभी इसे कहीं भी करने की आवश्यकता है। वास्तव में यह अक्सर थ्रेड के संदर्भ को पहले स्थान पर नहीं रखता है, या अपने धागे को प्रबंधित करने के लिए निष्पादक सेवा का उपयोग नहीं करता है।

जब मेरे पास कोई ऑब्जेक्ट है जिसमें Thread फ़ील्ड है, तो थ्रेड मरने पर अक्सर यह ऑब्जेक्ट मर जाता है, इस प्रकार फ़ील्ड को null एड आउट होने की आवश्यकता नहीं होती है।

मैं फोरक/जॉइन के लिए उपयोग किए गए थ्रेड पूल में भी उपयोग करता हूं। पृष्ठभूमि थ्रेड में कार्यों को करने के लिए यह एक हल्का वजन तरीका है क्योंकि यह धागे को इतना बना और नष्ट नहीं करता है।

ExecutorService fjp = ForkJoinPool.commonPool(); 

कचरा संग्रहण के लिए पात्र होने के नाते जरूरी नहीं है कि वस्तु स्मृति से निकाल दिया जाएगा। जब यह कचरा इकट्ठा होता है तो अंतर्निहित ऑपरेटिंग सिस्टम/जेवीएम के विवेकाधिकार पर होता है। लेकिन कोई कैसे सुनिश्चित कर सकता है (या तो जावा प्रोग्राम या बाहरी उपकरण के माध्यम से) कि ऑब्जेक्ट पूरी तरह से स्मृति से हटा दिया गया है?

आप और आम तौर पर कोशिश नहीं कर सकते हैं। जब आवश्यक हो तो जीसी संसाधनों को साफ कर देगा।

एक धागा एक बार यह अपनी दौड़() विधि खत्म मृत होने के लिए कहा जाता है, तो क्यों मैं अभी भी IsAlive() या getState() एक ही धागे वस्तु पर निष्पादित करने में सक्षम हो सकता है? दोनों कॉल क्रमशः झूठी और रननेबल लौटते हैं।

थ्रेड ऑब्जेक्ट किसी अन्य ऑब्जेक्ट की तरह है। जब तक आप इसका संदर्भ रखते हैं तब तक आप इस पर विधियों को कॉल कर सकते हैं।

3

तथ्य यह है कि थ्रेड निष्पादन समाप्त हो गया है, वस्तु के संदर्भ की वैधता को परिवर्तित नहीं करता है। जबकि आप उस संदर्भ को रखते हैं थ्रेड ऑब्जेक्ट कचरा नहीं किया जा सकता है।

इसका मतलब है कि जब आप थ्रेड का संदर्भ रखते हैं तो आप isAlive जैसी चीजें कॉल करने में सक्षम हैं। जब आप सभी संदर्भों को छोड़ देते हैं तो थ्रेड एकत्रित कचरा हो सकता है।

यदि आप उस वस्तु को कचरा होने से रोकने के बिना किसी ऑब्जेक्ट का संदर्भ रखना चाहते हैं तो आपको WeakReference का उपयोग करना होगा। जब आप इस तरह के संदर्भ का उपयोग करते हैं तो आपको यह देखने के लिए जांच करनी चाहिए कि ऑब्जेक्ट संदर्भित अभी भी मौजूद है या नहीं।

0

मुझे विश्वास है कि कचरा कलेक्टर एक वस्तु एकत्र करता है जब स्मृति में किसी ऑब्जेक्ट का कोई संदर्भ नहीं होता है। धागे के मामले में, प्रक्रिया चल रही है इसलिए थ्रेड ऑब्जेक्ट कचरा कलेक्टर द्वारा एकत्र नहीं किया जाएगा।

प्रत्येक ऑब्जेक्ट पेड़ में एक या अधिक रूट ऑब्जेक्ट्स होना चाहिए। जब तक आवेदन उन जड़ों तक पहुँच सकते हैं, पूरे वृक्ष के माध्यम से

javabook.compuware.com/content/memory/how-garbage-collection-works.aspx 
4

ऐसा लगता है कि आप जावा में unterstanding धागे के साथ आम ख़तरा पर ट्रिपिंग कर रहे हैं पहुंचा जा सकता है: धागा अपने आप में एक जावा वस्तु नहीं है। यह एक मूल संसाधन (निष्पादन का धागा) है। जैसे ही यह अपना कोड चला रहा है, इसे "स्मृति से हटा दिया जाएगा"।

Thread के कहने, दूसरे हाथ पर, अतिरिक्त नियम यह है कि यह कम से कम जब तक पहुंचा जा सकता के रूप में अंतर्निहित देशी धागा जीवित है रहता है के अलावा कोई भी अन्य वस्तु — के रूप में ही जीवन चक्र के साथ सिर्फ एक सादे जावा वस्तु है। यह इस तथ्य से निहित है कि आप हमेशा Thread.currentThread() पर कॉल कर सकते हैं।

तो, यदि आप किसी मृत धागे के प्रभारी Thread उदाहरण का संदर्भ बनाए रखते हैं, तो यह जादुई रूप से गायब नहीं होगा और इसकी सभी विधियां निर्दिष्ट के रूप में संचालित रहेंगी। आप वांछित के लिए इसे पकड़ सकते हैं।

आपके प्रश्न 2 के बारे में, स्मृति से किसी ऑब्जेक्ट को "निकालना" एक वर्चुअल अर्थहीन शब्द है। रनटाइम को वास्तव में संग्रहित वस्तुओं के बारे में कोई जानकारी नहीं है — वे हैं जिनके पास भूल गया है।

2

धागे के बारे में विचार करने के लिए दो चीजें हैं।

  1. चलने वाले थ्रेड ऑब्जेक्ट्स के पहले और उसके दौरान स्वयं जीसी जड़ें हैं, यानी: वे और उनके द्वारा दृढ़ता से सुलभ वस्तुओं को एकत्र नहीं किया जा सकता है।
  2. एक बार धागा चलने के बाद, यह एक सामान्य वस्तु होने के लिए "वापस" हो जाता है। वही जीसी नियम किसी भी अन्य वस्तु के रूप में उनके लिए लागू होते हैं। तो उदाहरण के लिए, जबकि आपके पास उनके लिए एक मजबूत संदर्भ है, वे एकत्र नहीं किए जाएंगे और हां, आप बिना किसी परेशानी के तरीकों पर कॉल कर सकते हैं।

तो मेरी सलाह "मृत" धागे की तरह आप प्रकार List या उदाहरण के लिए Map की एक वस्तु का इलाज होगा इलाज के लिए है। उन पर क्या लागू होता है जो चलने वाले धागे पर लागू होते हैं।

+0

जीसी जड़ें – ciamej

1

यदि यह रन() से लौटने के बाद कचरा संग्रह के लिए योग्य नहीं बनता है, तो क्या इसे करने के लिए इसे संदर्भित करना चाहिए?

यह हमेशा बेहतर करने के लिए स्पष्ट रूप से सेट वस्तुओं शून्य पर (यदि आपको विश्वास है कि वे भविष्य में उपयोग नहीं किया जाएगा रहे हैं) जीसी का काम थोड़ा आसान बनाने के लिए है।

class Test { 

protected void finalize() throws Throwable { 
    System.out.println("test finalized"); 
}; 

public static void main(String[] args) { 
    Thread t = new MyThread(); 
    t.start(); 
    Test test = new Test(); 

    try { 
     System.out.println(t.getState()); 
     // t.join(); 
     t = null; 
     test = null; 
     // System.out.println(t.getState()); 

     Thread.sleep(500); // change this to say 2 or 3 sec i.e, until run() completes. The thread object will be finalized 
     System.gc(); 
     System.out.println("gc call done.."); 
     Thread.sleep(1000); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 

}

class MyThread extends Thread { 

protected void finalize() throws Throwable { 
    System.out.println("MyThread instance finalized.."); 
}; 

@Override 
public void run() { 
    for (int i = 0; i < 5; i++) { 
     try { 
      Thread.sleep(300); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     System.out.println(i); 

    } 
} 

}

ओ/पी: मामले: 1 -> अगर धागा चल है जब जीसी करने के लिए कॉल किया जाता है।

RUNNABLE 
0 
gc call done.. 
test finalized 
1 
2 
3 
4 

मामले: 2 -> यदि धागा चलना समाप्त कर दिया जब जीसी करने के लिए कॉल किया जाता है।

 RUNNABLE 
    0 
    gc call done.. 
    test finalized 
    1 
    2 
    3 
    4 
MyThread instance finalized.. 

कचरा संग्रहण के लिए पात्र होने के नाते जरूरी नहीं है कि वस्तु स्मृति से निकाल दिया जाएगा। जब यह कचरा इकट्ठा होता है तो अंतर्निहित ऑपरेटिंग सिस्टम/जेवीएम के विवेकाधिकार पर होता है। लेकिन कोई कैसे सुनिश्चित कर सकता है (या तो जावा प्रोग्राम या बाहरी उपकरण के माध्यम से) कि ऑब्जेक्ट पूरी तरह से स्मृति से हटा दिया गया है?

जावा में, आप केवल कह सकते हैं जब वस्तुपहुँच योग्य नहीं हो जाता है (नहीं GCed, पहुँच योग्य नहीं।)। finalize() आपको बुलाया जाएगा जब आपका ओजेसी पहुंच योग्य बन जाएगा।

यदि एक थ्रेड मरने के बाद कहा जाता है कि यह एक रन थ्रेड() विधि समाप्त हो जाता है, तो मैं अभी भी उसी थ्रेड ऑब्जेक्ट पर एलीव() या getState() निष्पादित करने में सक्षम क्यों हो सकता हूं? दोनों कॉल क्रमशः झूठी और रननेबल लौटते हैं। - धागे ने अपना निष्पादन समाप्त कर दिया होगा। लेकिन यह अभी भी एक राज्य में होगा। को राज्य समाप्त कर दिया गया। आप इन विधियों को थ्रेड इंस्टेंस पर कॉल कर रहे हैं। तो, यह अभी भी कुछ राज्य डेटा रखता है।

+0

के लिए वोट दें वास्तव में दो राज्य हैं जो कोई समझ सकते हैं: * अंतिमकरण * और * अंतिम *। यह एक प्रेत संदर्भ कतार से प्राप्त किया जा सकता है। हालांकि, यहां तक ​​कि * अंतिम * का मतलब "स्मृति से हटाया गया" नहीं है। –

+0

@ मार्कोटोपॉलिक - सहमत। * अंतिमकृत * बस मतलब है कि उदाहरण अब * पहुंच योग्य नहीं है *। – TheLostMind

+0

* अंतिम पुनरुत्थान * का अर्थ है "पहुंचने योग्य", लेकिन निश्चित रूप से ऐसा नहीं, संभव पुनरुत्थान के कारण। तो हाँ, असल में केवल "अंतिमकृत" का मतलब है "निश्चित रूप से पहुंच योग्य नहीं"। –

संबंधित मुद्दे

 संबंधित मुद्दे