2012-04-30 17 views
17

संभव डुप्लिकेट:
Java Thread Garbage collected or notजावा धागे और कचरा कलेक्टर

निम्नलिखित वर्ग पर विचार करें:

class Foo implements Runnable { 

    public Foo() { 
     Thread th = new Thread (this); 
     th.start(); 
    } 

    public run() { 
    ... // long task 
    } 

} 

हम

करके Foo के कई उदाहरण बनाते हैं
new Foo(); 
new Foo(); 
new Foo(); 
new Foo(); 

(ध्यान दें कि हम उन्हें पॉइंटर नहीं रखते हैं)।

  1. ऐसे मामलों run() सिरों में से पहले धागा कचरा कलेक्टर द्वारा हटाया जा सकता है?

  2. दूसरे हाथ में, ऐसे मामलों `समय में धागा के बाद जीसी से निकाल दिया जाएगा: (दूसरे शब्दों में कोई संदर्भ Foo वस्तुओं के लिए है?) और, (') समाप्त हो जाती है, या कर रहे हैं हम स्मृति बर्बाद कर रहे हैं ("स्मृति रिसाव")?

  3. यदि कोई या तो 1. या 2. समस्या है, तो ऐसा करने का सही तरीका क्या है?

धन्यवाद

+0

आप वास्तव में इसे बहुत आसानी से जांच सकते हैं। –

+0

@Quaternion, हाँ शायद, लेकिन उस दूसरे प्रश्न का शब्द वास्तव में "obfuscated" और समझने में मुश्किल है, imho। – cibercitizen1

+1

यह एक डुप्लिकेट नहीं है। जुड़ा हुआ प्रश्न "पूरा होने के बाद भी कचरा इकट्ठा किया जाएगा" के पहलू को संबोधित नहीं करता है (मैं इसे विशेष रूप से पूछने वाला था)। यह केवल "पहचाने जाने पर जीसीएड नहीं होगा" के पहलू को पूछता/जवाब देता है। यह सवाल मेरी राय में बेहतर है। – bluenote10

उत्तर

16
  1. किसी भी वस्तु जो एक सक्रिय धागा द्वारा संदर्भित है डी-आवंटित नहीं किया जा सकता है।
  2. हां, 'रन()' सिरों में धागे के बाद जीसी द्वारा उदाहरण हटा दिए जाएंगे।
  3. कोई जांच नहीं।
+0

कृपया मुझे यह बताएं कि आपको यह निष्कर्ष कहां मिलता है। – Chao

2
  1. Foo वस्तु थ्रेड द्वारा संदर्भित है। थ्रेड को हर समय अपने रन के दौरान संदर्भित किया जाता है। इसलिए यह कचरा नहीं होगा।
  2. कोई मेमोरी लीक नहीं है। थ्रेड समाप्त हो जाएगा और इस प्रक्रिया में कचरा इकट्ठा किया जाएगा और Foo ऑब्जेक्ट भी होगा।
  3. यह ठीक काम करना चाहिए।
10
  1. ऐसे मामलों समय में धागा से पहले कचरा कलेक्टर द्वारा हटाया जा सकता है() समाप्त हो जाती है? निर्माता जी सी चल रहा है वह वस्तु एकत्र नहीं करेगा: (दूसरे शब्दों में वहाँ फू वस्तुओं के लिए किसी भी संदर्भ है?)

नं। अन्यथा भी सरल:

Customer c = new Customer(); 

जबकि Customer के निर्माता चल रहा है विफल हो सकता है। दूसरी ओर जब आप एक नया धागा शुरू करते हैं, तो थ्रेड ऑब्जेक्ट एक नया जीसी रूट बन जाता है, इसलिए उस ऑब्जेक्ट द्वारा संदर्भित सबकुछ कचरा संग्रह का विषय नहीं है।

  1. और, दूसरे हाथ में, ऐसे मामलों `रन() 'समाप्त होता है में धागा के बाद जी सी द्वारा हटा दिया जाएगा, या हम स्मृति (" स्मृति रिसाव ") बर्बाद कर रहे हैं?

एक बार धागा किया जाता है, यह अब एक जीसी जड़ है। यदि उस थ्रेड ऑब्जेक्ट को कोई अन्य कोड इंगित नहीं करता है, तो यह कचरा इकट्ठा होगा।

  1. या तो 1. या 2. एक समस्या है, तो क्या यह करने के लिए सही तरीका है?

आपका कोड ठीक है। हालांकि:

  • एक निर्माता में एक नया धागा शुरू करने को देखने

  • चल रहे सभी धागे के लिए एक संदर्भ रखने की इकाई परीक्षण बिंदु से एक गरीब विचार है फायदेमंद हो सकता है अगर उदाहरण के लिए आप बाद में इन धागे को बाधित करना चाहते हैं।

+0

@ मार्कोटोपॉलिक: ओह, यह करता है! ओपी 'थ्रेड' कन्स्ट्रक्टर को 'यह' पास कर रहा है जो 'फू' का उदाहरण होता है। हालांकि यह सही है - अगर 'फू' में कुछ राज्य है, तो सभी राज्य चर जीसी से बचेंगे क्योंकि उन्हें 'फू' द्वारा संदर्भित किया जाता है - और 'फू' को धागे द्वारा संदर्भित किया जाता है। –

+4

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

7

एक धागा समूह add it to the default group होगा निर्दिष्ट किए बिना एक नया धागा शुरू:

यदि समूह रिक्त है और वहाँ एक सुरक्षा प्रबंधक है, समूह सुरक्षा प्रबंधक के getThreadGroup विधि से निर्धारित होता है। यदि समूह शून्य है और कोई सुरक्षा प्रबंधक नहीं है, या सुरक्षा प्रबंधक की getThreadGroup विधि शून्य लौटाती है, तो समूह थ्रेड ग्रुप को थ्रेड के रूप में सेट किया गया है जो नया धागा बना रहा है।

समूह उस समय तक धागे का संदर्भ रखेगा जब तक कि यह जीवित न हो, इसलिए उस समय जीसीडी नहीं किया जा सकता है।

जब कोई थ्रेड समाप्त हो जाता है (= जब run() किसी भी कारण से लौटाता है), थ्रेड समूह से थ्रेड हटा दिया जाता है। यह निजी विधि exit() में होता है जिसे देशी कोड से कहा जाता है। यह वह समय है जब धागे का अंतिम संदर्भ गुम हो जाता है और यह जीसी के लिए योग्य हो जाता है।

ध्यान दें कि कोड इंगित करता है कि ThreadGroupnull हो सकता है लेकिन ऐसा नहीं है। विभिन्न नल-चेक दुर्लभ मामले में एनपीई से बचने के लिए हैं कि कुछ गलत हो जाता है। Thread.init() में, यदि आप थ्रेड समूह निर्धारित नहीं कर पा रहे हैं तो आपको एनपीई मिलेंगे।

0

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

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

+0

फू ऑब्जेक्ट्स रन विधि int नहीं बनाते हैं, लेकिन, उदाहरण के लिए, मुख्य में। – cibercitizen1

+0

बस एक और कोड ब्लॉक, कोई चीज़ नहीं बदलता है –

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