ExecutorService पर शटडाउन () कॉल करने का कारण


84

मैं इसके बारे में पिछले कुछ घंटों में काफ़ी पढ़ रहा था, और मैं बस नहीं किसी भी कारण (देख सकते हैं वैध कॉल करने के लिए कारण) shutdown()पर ExecutorService, जब तक कि हम एक humongous अनुप्रयोग है जो स्टोर, दर्जनों और उस के लिए इस्तेमाल नहीं कर रहे हैं विभिन्न निष्पादक सेवाओं के दर्जनों एक लम्बा समय।

केवल एक चीज (जो मैं इकट्ठा करता हूं) शटडाउन करता है, वह वही करता है जो एक सामान्य थ्रेड एक बार करता है। जब सामान्य थ्रेड रननीय (या कॉल करने योग्य) की रन विधि को समाप्त कर देगा, तो इसे एकत्र करने के लिए कचरा संग्रह में पास किया जाएगा। निष्पादक सेवा के साथ धागे बस पकड़ में डाल दिए जाएंगे, उन्हें कचरा संग्रह के लिए टिक नहीं किया जाएगा। उसके लिए शटडाउन की जरूरत है।

ठीक है मेरे सवाल पर वापस। क्या ExecutorServiceबहुत बार, या यहां तक ​​कि कुछ कार्यों को प्रस्तुत करने के बाद भी शटडाउन कॉल करने का कोई कारण है? मैं उस मामले को पीछे छोड़ना चाहूंगा जो कोई कर रहा है और इसके ठीक बाद कॉल करता है awaitTermination()क्योंकि यह मान्य है। एक बार जब हम ऐसा कर लेते हैं, तो हमें फिर से एक नया ExecutorServiceकाम करना पड़ता है, वही काम करने के लिए। क्या ExecutorServiceथ्रेड्स का पुन: उपयोग करने के लिए संपूर्ण विचार नहीं है ? तो ExecutorServiceइतनी जल्दी नष्ट क्यों ?

क्या यह तर्कसंगत तरीका नहीं है कि आप बस ExecutorService(या कितने आप की जरूरत के आधार पर) बना सकते हैं, फिर आवेदन चलाने के दौरान उनके पास आने वाले कार्यों को पास करने के लिए, और फिर आवेदन से बाहर निकलने या कुछ अन्य महत्वपूर्ण चरणों में उन निष्पादकों को बंद कर दें। ?

मुझे कुछ अनुभवी कोडर्स से जवाब चाहिए, जो एक्सक्लूसिव सर्विसेस का उपयोग करके बहुत सारे एसिंक्रोनस कोड लिखते हैं।

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

कॉमन्सवेयर की टिप्पणी के कारण मैंने पोस्ट को तटस्थ बना दिया। मुझे वास्तव में इसके बारे में बहस करने में कोई दिलचस्पी नहीं है और ऐसा लगता है कि यह वहां अग्रणी है। मुझे केवल सीखने में दिलचस्पी है कि मैंने अनुभवी डेवलपर्स से यहां क्या पूछा, अगर वे अपने अनुभवों को साझा करने के लिए तैयार हैं। धन्यवाद।


3
"मुझे कई बार नमूना कोड दिखाई देते हैं, जिसमें हर समय, कार्यों को प्रस्तुत करने या निष्पादित करने के तुरंत बाद एक शटडाउन () आह्वान होता है" - अपने दावों का सबूत देने के लिए हाइपरलिंक का उपयोग करने के लिए स्वतंत्र महसूस करें। व्यक्तिगत रूप से, मैंने कभी कोई "नमूना कोड" नहीं देखा है जो आप करते हैं। यह संभव है कि आप कुछ गलत कर रहे हैं, और हम केवल आपको इंगित कर सकते हैं कि अगर हम जानते हैं कि "नमूना कोड" आप क्या जांच रहे हैं।
कॉमन्सवेयर

4
हाय कॉमन्सवेयर। सबसे पहले, मुझे आपकी ओर (या ऐसा लगता है) एक आक्रामक स्वर दिखाई देता है, जो मुझे लगता है कि यहाँ मान्य नहीं है। मैं लोगों को नकारात्मक तरीके से चित्रित करने की कोशिश नहीं कर रहा था। आपके उद्धरण के लिए, मैं ज्यादातर जावा IV संस्करण में थिंकिंग इन, मल्टीटास्किंग भाग के बारे में बात कर रहा था। आप ब्रूस एकेल के उदाहरणों में इसके कई उदाहरण देख सकते हैं। वे ज्यादातर सरल हैं, लेकिन ब्रूस ने मुझ पर जो प्रभाव डाला, वह कभी कम नहीं हुआ, शटडाउन का उपयोग बहुत बार किया गया। किसी भी तरह से, आपने किसी ऐसी चीज़ पर ध्यान केंद्रित किया जो मेरी पोस्ट का मुख्य हिस्सा नहीं था। मैंने उन हिस्सों को हटा दिया क्योंकि मैं वास्तव में इसके बारे में बहस नहीं करना चाहता।
लुकास

1
hay @CommonsWare इन द लावा बुक इन थिंकिंग बाय ब्रूस Eckel..in कंसीडर / एक्ज़ीक्यूटर पेज 804 फोर्थ एडिशन, वह हमेशा शटडाउन का उपयोग करता है () सरल ऐप में कार्य प्रस्तुत करने या निष्पादित करने के बाद सही तरीके से बताता है कि एक्सेक्यूटर लुकास के रूप में कैसे काम करता है
त्रुटि

2
मुझे पता है कि यह एक पुरानी पोस्ट है, लेकिन मुझे लगता है कि ओपी का सवाल अभी भी खड़ा है और मान्य है। मैं कई नमूना कोड भी ले आया हूं, जहां "निष्पादित होने के बाद एक शटडाउन () मंगलाचरण सही है" ()। tutorials.jenkov.com/java-util-concurrent/executorservice.html (पहला ट्यूटोरियल जो तब आता है जब आप Google "java निष्पादक उदाहरण")
baekacaek

धन्यवाद, मेरा एक ही सवाल था कि इन "नमूना कोड" के साथ क्या हुआ। journaldev.com/2340/…
ग्रेगॉर्डी

जवाबों:


57

shutdown()निष्पादक सेवा के लिए और अधिक काम भेजने के लिए रोकता है ग्राहकों: विधि एक बात करता है। इसका मतलब है कि सभी मौजूदा कार्य तब भी पूरे होने तक चलेंगे जब तक कि अन्य कार्य नहीं किए जाते। यह अनुसूचित कार्यों के लिए भी सत्य है, उदाहरण के लिए, अनुसूचित शेड्यूलर सेवा के लिए: निर्धारित कार्य के नए उदाहरण नहीं चलेंगे। यह विभिन्न परिदृश्यों में उपयोगी हो सकता है।

मान लेते हैं कि आपके पास एक सांत्वना अनुप्रयोग है जिसमें एक निष्पादक सेवा है जो N कार्य चला रही है। यदि उपयोगकर्ता CTRL-C को हिट करता है, तो आप आवेदन को समाप्त करने की उम्मीद करते हैं, संभवतः सुंदर रूप से। इनायत का क्या मतलब है? हो सकता है कि आप चाहते हैं कि आपका एप्लिकेशन निष्पादक सेवा में अधिक कार्य प्रस्तुत करने में सक्षम न हो और साथ ही आप अपने मौजूदा एन कार्यों को पूरा करने के लिए इंतजार करना चाहते हैं। आप अंतिम उपाय के रूप में शटडाउन हुक का उपयोग करके इसे प्राप्त कर सकते हैं:

final ExecutorService service = ... // get it somewhere

Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Performing some shutdown cleanup...");
        service.shutdown();
        while (true) {
            try {
                System.out.println("Waiting for the service to terminate...");
                if (service.awaitTermination(5, TimeUnit.SECONDS)) {
                    break;
                }
            } catch (InterruptedException e) {
            }
        }
        System.out.println("Done cleaning");
    }
}));

यह हुक सेवा को बंद कर देगा, जो आपके आवेदन को नए कार्य प्रस्तुत करने से रोकेगा, और जेवीएम को बंद करने से पहले सभी मौजूदा कार्यों को पूरा करने की प्रतीक्षा करेगा। प्रतीक्षारत समाप्ति 5 सेकंड के लिए अवरुद्ध हो जाएगी और सेवा बंद होने पर सही वापस आ जाएगी। यह एक लूप में किया जाता है ताकि आप सुनिश्चित करें कि सेवा अंततः बंद हो जाएगी। InterruptedException हर बार निगल जाती है। यह एक निष्पादक सेवा को बंद करने का सबसे अच्छा तरीका है जो आपके सभी एप्लिकेशन पर पुन: उपयोग किया जाता है।

यह कोड सही नहीं है। जब तक आप पूरी तरह से सकारात्मक नहीं हो जाते हैं, तब तक आपके कार्य अंततः समाप्त हो जाएंगे, आप किसी दिए गए समय के लिए प्रतीक्षा करना चाहते हैं और फिर बस बाहर निकलें, चल रहे धागों का त्याग कर सकते हैं। इस मामले में यह भी समझ shutdownNow()में आता है कि रनिंग थ्रेड्स को बाधित करने के अंतिम प्रयास में समय समाप्त होने के बाद कॉल किया shutdownNow()जाएगा ( यह आपको चलाने के लिए इंतजार कर रहे कार्यों की एक सूची भी देगा)। यदि आपके कार्यों को रुकावट का जवाब देने के लिए डिज़ाइन किया गया है तो यह ठीक काम करेगा।

एक और दिलचस्प परिदृश्य यह है कि जब आपके पास शेड्यूल किए गए कार्य को शेड्यूल करने के लिए शेड्यूल किया गया है। आवधिक कार्यों की श्रृंखला को रोकने का एकमात्र तरीका कॉल करना है shutdown()

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


देर से प्रतिक्रिया के लिए खेद Giovanni, और उस btw के लिए धन्यवाद। हां, मुझे पता है कि एक्सेक्यूटर कैसे काम करता है, जिसे मैंने अपने प्रश्न में समझाने की कोशिश की। शटडाउन वह करता है जो आपने कहा था, और यह कचरा कलेक्टर को उन मृत थ्रेड्स को इकट्ठा करने की अनुमति भी देता है, और एग्जिक्यूटर सर्विस को इकट्ठा करने के लिए प्रभावी रूप से। मेरा प्रश्न विशिष्ट था। आपके द्वारा ExecutorService पर कुछ भी सबमिट करने / निष्पादित करने के तुरंत बाद हर समय "शटडाउन ()" कॉल करने का कोई कारण नहीं है। प्रश्न का दूसरा भाग एंड्रॉइड आर्किटेक्चर के संबंध में कड़ाई से है। यदि पिछले का उत्तर नहीं है, तो कब और किस दौरान शटडाउन कॉल करना है। जीवन चक्र।
लुकास

3
हर समय शटडाउन () कॉल करने का कोई कारण नहीं है। वास्तव में, यह पूरी तरह से गलत काम हो सकता है क्योंकि यह आपको निष्पादक सेवा को फिर से उपयोग करने से रोक देगा। सेवा के जीवन चक्र के अंत में इसे कॉल करने का कारण यह है कि धागे अंत में कचरा एकत्र किए जा सकते हैं जैसा आपने देखा था। यदि आप नहीं करते हैं, तो वे धागे निष्क्रिय होने के बावजूद जेवीएम को जीवित रखेंगे।
गियोवन्नी बोट्टा

"हर समय शटडाउन () कॉल करने का कोई कारण नहीं है। वास्तव में, यह करने के लिए गलत गलत काम हो सकता है क्योंकि यह आपको निष्पादक सेवा का पुन: उपयोग करने से रोक देगा"। यह वास्तव में मेरा तर्क है, और मूल प्रश्न से मेरी दुविधा है। तो फिर से कहना है, सवाल यह है: मुझे एंड्रॉइड जीवनचक्र में अपने कार्यकारी सेवा को कब बंद करना चाहिए?
लुकास

2
मेरे पास कोई एंड्रॉइड अनुभव नहीं है, लेकिन मुझे लगता है कि जब जेवीएम आखिरकार बाहर निकलने की अनुमति दे, तो आपको इसे बंद कर देना चाहिए।
गियोवन्नी बोट्टा

3
समझा। मेरा सुझाव है कि आप कैश्ड थ्रेड पूल का उपयोग करें और इस पर कभी कॉल न करें shutdown()ताकि अनावश्यक होने पर आप संसाधनों को बर्बाद न करें। यदि एप्लिकेशन बंद हो जाता है, तो पूल में धागे अंततः कचरा एकत्र हो जाएंगे (बाद में वे डिफ़ॉल्ट रूप से 60 सेकंड के लिए निष्क्रिय हैं)। ध्यान दें कि यदि आप चाहते हैं कि पूल बँधा हो या एक अलग थ्रेड लाइफ टाइम चाहिए तो आप ThreadPoolExecutorसीधे बना सकते हैं ।
जियोवन्नी बोटा

13

क्या ExecutorService के लिए थ्रेड्स का पुन: उपयोग करने के लिए संपूर्ण विचार नहीं है? तो इतनी जल्दी ExecutorService को क्यों नष्ट करें?

हाँ। आपको ExecutorServiceबार - बार नष्ट नहीं करना चाहिए और फिर से बनाना चाहिए । ExecutorServiceजब आपको आवश्यकता हो तो प्रारंभ करें (ज्यादातर स्टार्ट-अप पर) और इसे तब तक सक्रिय रखें जब तक आप इसके साथ नहीं हो जाते।

क्या यह एक्सक्लूसिव सर्विस बनाने के लिए एक तर्कसंगत तरीका नहीं है (या आपको कितने की जरूरत है, इस पर निर्भर करता है), तो एप्लिकेशन रनिंग के दौरान उन्हें एक बार पास आने वाले कार्यों को पास करें, और फिर आवेदन से बाहर निकलने या कुछ अन्य महत्वपूर्ण चरणों को बंद कर दें। निष्पादकों?

हाँ। यह ExecutorServiceमहत्वपूर्ण है जैसे आवेदन निकास आदि पर बंद करना तर्कसंगत है ।

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

मान लें कि ExecutorServiceआपके आवेदन में विभिन्न गतिविधियों में साझा किया गया है। प्रत्येक गतिविधि को समय के विभिन्न अंतराल पर रोका / फिर से शुरू किया जाएगा और अभी भी आपको ExecutorServiceअपने आवेदन के अनुसार एक की आवश्यकता होगी ।

ExecutorServiceगतिविधि जीवन चक्र विधियों की स्थिति को प्रबंधित करने के बजाय , ExecutorService प्रबंधन (निर्माण / शटडाउन) को अपनी कस्टम सेवा में स्थानांतरित करें ।

ExecutorServiceसेवा => में बनाएं onCreate()और इसे ठीक से बंद करेंonDestroy()

बंद करने का अनुशंसित तरीका ExecutorService:

कैसे ठीक से जावा ExecutorService बंद करने के लिए


3

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

संदर्भ पुस्तक

चापर: १४ पृष्ठ: :१४


0

ExecutorService पर शटडाउन () कॉल करने का कारण

आज मुझे ऐसी स्थिति का सामना करना पड़ा जहां मुझे मशीन के तैयार होने तक इंतजार करना पड़ता है, उस मशीन पर कार्यों की एक श्रृंखला शुरू करने से पहले।

मैं इस मशीन को एक REST कॉल करता हूं, अगर मुझे 503 (सर्वर अनुपलब्ध) प्राप्त नहीं होता है तो मशीन मेरे अनुरोधों को संसाधित करने के लिए तैयार है। इसलिए, मैं प्रतीक्षा करता हूं जब तक कि मुझे पहले REST कॉल के लिए 200 (सफलता) न मिल जाए।

इसे प्राप्त करने के कई तरीके हैं, मैंने एक X थ्रेड बनाने के लिए ExecutorService का उपयोग किया और इसे प्रत्येक X सेकंड के बाद चलाने के लिए शेड्यूल किया। इसलिए, मुझे एक शर्त पर इस धागे को रोकने की जरूरत है, इसे देखें ...

final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
    Runnable task = () -> {
        try {
            int statusCode = restHelper.firstRESTCall();

            if (statusCode == 200) {
                executor.shutdown();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    };

    int retryAfter = 60;
    executor.scheduleAtFixedRate(task, 0, retryAfter, TimeUnit.SECONDS);

दूसरा पक्ष प्रश्न, एंड्रॉइड प्लेटफॉर्म के साथ थोड़ा छोटा सौदा।

शायद मैं जवाब दे सकता हूं अगर आप थोड़ा और संदर्भ प्रदान करेंगे! Android के विकास के साथ मेरे अनुभव से भी शायद ही आपको थ्रेड्स की आवश्यकता हो। क्या आप एक गेम या एक ऐप विकसित कर रहे हैं जिसे प्रदर्शन के लिए थ्रेड्स की आवश्यकता है? यदि नहीं, तो एंड्रॉइड में आपके पास उस परिदृश्य की समस्याओं से निपटने के अन्य तरीके हैं जो मैंने ऊपर बताए हैं। आप संदर्भ के आधार पर इसके बजाय टाइमर, एस्किंटस्क या हैंडलर या लोडर का उपयोग कर सकते हैं। इसका कारण यह है कि अगर UIThread लंबे समय तक इंतजार करता है तो आपको पता है कि क्या होता है: /


0

यह नियोजित उपक्रमों के लिए वास्तविक है, जैसे कि, शेड्यूल किए गए कार्यभार के लिए: बुक किए गए असाइनमेंट के नए मामले नहीं चलेंगे।

हमें उम्मीद है कि आपके पास एक आराम से आवेदन होना चाहिए जिसमें एक एजेंट प्रशासन है जो एन एरंड चला रहा है।

मैं नहीं पकड़ रहा हूँ यह अर्थहीन है? शायद आपको एजेंट प्रशासन को अधिक असाइनमेंट जमा करने के विकल्प के लिए अपने आवेदन की आवश्यकता होती है और इस बीच आपको अपने वर्तमान एन उपक्रमों को समाप्त करने के लिए तंग बैठने की आवश्यकता होती है।

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

इस घटना में कि आपकी गतिविधियाँ हस्तक्षेप करने के लिए प्रतिक्रिया करने का इरादा है, यह ठीक काम करेगा।

एक और पेचीदा स्थिति वह बिंदु है जिस पर आपके पास एक शेड्यूल्ड एक्ज़ीक्यूटर सर्विस है जो एक गतिविधि को खेलता है।

गतिविधि की श्रृंखला को रोकने का सबसे अच्छा तरीका शटडाउन कॉल करना है ()

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