जावा थ्रेड कचरा एकत्र किया है या नहीं


85

यह सवाल कुछ साइट पर पोस्ट किया गया था। मुझे वहां सही उत्तर नहीं मिले, इसलिए मैं इसे फिर से यहां पोस्ट कर रहा हूं।

public class TestThread {
    public static void main(String[] s) {
        // anonymous class extends Thread
        Thread t = new Thread() {
            public void run() {
                // infinite loop
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                    // as long as this line printed out, you know it is alive.
                    System.out.println("thread is running...");
                }
            }
        };
        t.start(); // Line A
        t = null; // Line B
        // no more references for Thread t
        // another infinite loop
        while (true) {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
            }
            System.gc();
            System.out.println("Executed System.gc()");
        } // The program will run forever until you use ^C to stop it
    }
}

मेरी क्वेरी किसी थ्रेड को रोकने के बारे में नहीं है। मुझे मेरे प्रश्न का उत्तर दें। लाइन ए (ऊपर कोड देखें) एक नया थ्रेड शुरू करता है; और लाइन बी धागा संदर्भ को अशक्त बनाते हैं। तो, JVM में अब थ्रेड ऑब्जेक्ट (जो चालू स्थिति में है) जिसमें कोई संदर्भ मौजूद नहीं है (जैसा कि लाइन में t = null है)। तो मेरा सवाल यह है कि यह धागा (जिसका मुख्य धागे में कोई संदर्भ नहीं है) तब तक चलता रहता है जब तक कि मुख्य धागा नहीं चलता। मेरी समझ के अनुसार, थ्रेड ऑब्जेक्ट कचरा एकत्र किया जाना चाहिए था पोस्ट बी। मैंने 5 मिनट और अधिक के लिए इस कोड को चलाने की कोशिश की, जावा रनटाइम को GC चलाने के लिए अनुरोध किया, लेकिन थ्रेड केवल बंद नहीं होता है।

आशा है कि इस बार कोड और प्रश्न दोनों स्पष्ट हैं।

जवाबों:


123

एक रनिंग थ्रेड को तथाकथित कचरा संग्रहण रूट माना जाता है और यह उन चीजों में से एक है जो सामान को कचरा एकत्र करने से रोकते हैं। जब कचरा संग्राहक यह निर्धारित करता है कि आपकी वस्तु ' पहुंच योग्य ' है या नहीं, तो यह हमेशा ऐसा करता है कि कचरा संग्राहक जड़ों के सेट को संदर्भ बिंदुओं के रूप में उपयोग किया जाता है।

इस पर विचार करें, आपका मुख्य धागा कचरा क्यों नहीं एकत्र किया जा रहा है, कोई भी उस एक को संदर्भित नहीं कर रहा है।


16
यह जवाब, जैसा कि यह वर्तमान में खड़ा है, सवाल उठाता है कि क्या धागे को जीसी'एड (वे समाप्त होने के बाद) किया जा सकता है। के बाद से इस सवाल का डुप्लिकेट के रूप में चिह्नित किया गया है यह एक है, यह उल्लेखनीय है कि धागे नहीं रह गया है के रूप में "कचरा संग्रहण जड़ों" चिह्नित किया जाएगा के बाद वे समाप्त, और इस प्रकार, वे जी सी के लिए पहुंच योग्य हो जाते हैं।
bluenote10

13
अंतिम वाक्य मर्मज्ञ है: "आपका मुख्य धागा कचरा क्यों नहीं हो रहा है ..."।
निर्धारक

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

1
जितना अधिक उत्तर मैं पढ़ता हूं, उतना ही भ्रमित हो जाता हूं, लेकिन हाँ, मुख्य धागे को इकट्ठा क्यों नहीं किया जा रहा है, इसके बारे में विचार करने के लिए कुछ है। लेकिन मूल प्रश्न पर वापस आते हैं, अगर बच्चे के धागे कुछ वस्तुओं का निर्माण करते हैं, तो यह GCed नहीं होगा क्योंकि माता-पिता का धागा अभी भी चल रहा है और बच्चे के धागे का संदर्भ रखता है, भले ही वे 'भाग' गए हों (!! ??)
राहुल कुमार

@Groostav एक धागा जो जुड़ गया है, वह नहीं चल रहा है, इसलिए यह कचरा संग्रहण रूट नहीं है। लेकिन जब माता-पिता ने फोन किया child.join(), तो इसका संदर्भ था child। यदि वह संदर्भ (और कोई भी एक) खारिज नहीं किया जाता है, तो बच्चे के धागे को GCed नहीं किया जा सकता है।
Blaisorblade

23

जैसा कि समझाया गया था, रनिंग थ्रेड परिभाषा के अनुसार, जीसी के प्रति प्रतिरक्षा हैं। जीसी अपना काम "जड़ों" को स्कैन करके शुरू करता है, जिन्हें हमेशा उपलब्ध माना जाता है; जड़ों में वैश्विक चर ("जावा-टॉक में स्थिर क्षेत्र") और सभी चलने वाले धागे के ढेर शामिल हैं (यह कल्पना की जा सकती है कि एक रनिंग थ्रेड का ढेर संबंधित Threadउदाहरण को संदर्भित करता है )।

हालाँकि, आप एक थ्रेड को "डेमॉन" थ्रेड बना सकते हैं (देखें Thread.setDaemon(boolean))। एक डेमन थ्रेड गैर-डेमॉन थ्रेड से अधिक कचरा-संग्रह नहीं है, लेकिन जेवीएम बाहर निकलता है जब सभी चलने वाले धागे डेमन होते हैं। इसकी कल्पना करने का एक तरीका यह है कि प्रत्येक थ्रेड, जब यह समाप्त हो जाता है, तो जांचता है कि क्या कुछ गैर-डेमन रनिंग थ्रेड हैं; यदि नहीं, तो समाप्त होने वाला धागा System.exit()कॉल को बाध्य करता है, जो JVM (रनिंग डेमन थ्रेड्स को मारकर) को बाहर निकालता है। यह जीसी से संबंधित मुद्दा नहीं है; एक तरह से, थ्रेड्स मैन्युअल रूप से आवंटित किए जाते हैं। हालांकि, यह कैसे जेवीएम अर्द्ध-दुष्ट धागे को सहन कर सकता है। यह आमतौर पर Timerउदाहरणों के लिए उपयोग किया जाता है ।


19

JVM में सभी रनिंग थ्रेड्स का संदर्भ है।

कोई भी धागा (या इसके द्वारा संदर्भित चीजें) कचरा-एकत्र नहीं किया जाएगा, जबकि यह अभी भी चल रहा है।


13

थ्रेड कचरा एकत्र नहीं किया जाता है क्योंकि उन थ्रेड्स के संदर्भ हैं जो आप नहीं देख सकते हैं। उदाहरण के लिए, रनटाइम सिस्टम में संदर्भ होते हैं।

जब थ्रेड बनाया जाता है तो इसे वर्तमान थ्रेड समूह में जोड़ा जाता है। आप वर्तमान थ्रेड समूह में थ्रेड्स की एक सूची प्राप्त कर सकते हैं, इसलिए इसका संदर्भ प्राप्त करने का एक और तरीका है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.