2012-12-14 35 views
52
में डेमॉन को

मैं जावा 1.6 में एक ExecutoreService उपयोग कर रहा हूँ,एक ExecutorService टर्निंग जावा

ExecutorService pool = Executors.newFixedThreadPool(THREADS). 

जब मेरे मुख्य थ्रेड (सभी कार्य थ्रेड पूल द्वारा कार्रवाई के साथ) समाप्त हो गया है, इस पूल से बस शुरू कर दिया मैं जब तक नीचे बंद से मेरा कार्यक्रम नहीं कर पाएगा स्पष्ट रूप से कहते हैं

pool.shutdown(); 

मैं किसी भी तरह आंतरिक धागा मोड़ एक deamon धागा में इस पूल द्वारा प्रयोग किया जाता के प्रबंधन के द्वारा इस कॉल करने के लिए होने से बच सकते हैं? या मुझसे यहां कुछ छूट रहा है।

+1

वर्तमान में स्वीकार जवाब के लेखक दृष्टिकोण Marco13 द्वारा पोस्ट की गई पढ़ने सुझाव है कि के रूप में मैं: के बाद से समाधान वर्णित http://stackoverflow.com/a/29453160/1393766 और उसके लिए मेरे पद से स्वीकृति चिह्न बदल रहा है, वहाँ शायद है सबसे सरल और जो आप मूल रूप से हासिल करना चाहते थे उसे बंद कर देता है। – Pshemo

+0

@Pshemo मुझे आपसे असहमत होने दें ... कृपया मार्को 13 के उत्तर के तहत मेरी टिप्पणी देखें। –

+0

@Pshemo Vladimirs संकेत के संदर्भ में, आप इस तथ्य को इंगित करने पर विचार कर सकते हैं कि "सरल" समाधान हमेशा पसंदीदा नहीं हो सकता है। – Marco13

उत्तर

71

शायद सबसे सरल और पसंदीदा समाधान Marco13's answer में है इसलिए मतभेद मत बनो (मेरा जवाब कुछ साल पुराना है) या स्वीकृति चिह्न (इसका मतलब यह है कि मेरा समाधान ओपी परिस्थितियों के लिए उपयुक्त था कि यह सर्वोत्तम नहीं है) ।


आप ThreadFactory का उपयोग डेमॉन को निर्वाहक अंदर धागे सेट करने के लिए कर सकते हैं। यह निष्पादक सेवा को इस तरह से प्रभावित करेगा कि यह डेमॉन थ्रेड भी बन जाएगा, इसलिए यह (और इसके द्वारा नियंत्रित धागे) बंद हो जाएंगे यदि कोई अन्य गैर-डिमन थ्रेड नहीं होगा।

ExecutorService exec = Executors.newFixedThreadPool(4, 
     new ThreadFactory() { 
      public Thread newThread(Runnable r) { 
       Thread t = Executors.defaultThreadFactory().newThread(r); 
       t.setDaemon(true); 
       return t; 
      } 
     }); 

exec.execute(YourTaskNowWillBeDaemon); 

लेकिन आप निष्पादक जो अपने कार्य को खत्म करने देगा, और एक ही समय में स्वचालित रूप से अपने shutdown() विधि कॉल होगा जब आवेदन पूरा हो गया है प्राप्त करना चाहते हैं, तो आप रैप करने के लिए चाहते हो सकता है: यहाँ सरल उदाहरण है Guava'sMoreExecutors.getExitingExecutorService के साथ आपका निष्पादक।

ExecutorService exec = MoreExecutors.getExitingExecutorService(
     (ThreadPoolExecutor) Executors.newFixedThreadPool(4), 
     100_000, TimeUnit.DAYS//period after which executor will be automatically closed 
          //I assume that 100_000 days is enough to simulate infinity 
); 
//exec.execute(YourTask); 
exec.execute(() -> { 
    for (int i = 0; i < 3; i++) { 
     System.out.println("daemon"); 
     try { 
      TimeUnit.SECONDS.sleep(1); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
}); 
+1

भले ही यह उत्तर स्वीकार कर लिया गया था, मुझे नहीं लगता कि यह ओपी का इरादा है: मुझे लगता है कि सभी कार्यों को संसाधित होने पर प्रोग्राम बंद होना चाहिए। निष्पादकों के धागे को 'डेमन' पर सेट करते समय, प्रोग्राम तब भी बाहर निकल जाएगा जब कार्य अभी भी चल रहे हैं। –

+0

@ArnoutEngelen मैंने वैकल्पिक दृष्टिकोण देने के लिए अपना उत्तर अपडेट किया जो इस समस्या को हल करता है लेकिन मेरा मानना ​​है कि [मार्को 13 का पोस्ट] (http://stackoverflow.com/a/29453160/1393766) में सबसे अच्छा तरीका है। – Pshemo

4

हां।

आपको बस अपना खुद का ThreadFactory कक्षा बनाने की आवश्यकता है जो नियमित धागे की बजाय डेमॉन थ्रेड बनाता है।

26

वहां पहले से ही है एक ExecutorService कि निष्क्रियता की एक निश्चित अवधि के बाद सभी थ्रेड समाप्त हो जाता है बनाने के लिए एक में निर्मित कार्यक्षमता: आप एक ThreadPoolExecutor बनाने के लिए, यह वांछित समय जानकारी पारित कर सकते हैं, और फिर इस निष्पादक पर allowCoreThreadTimeout(true) फोन सेवा:

/** 
* Creates an executor service with a fixed pool size, that will time 
* out after a certain period of inactivity. 
* 
* @param poolSize The core- and maximum pool size 
* @param keepAliveTime The keep alive time 
* @param timeUnit The time unit 
* @return The executor service 
*/ 
public static ExecutorService createFixedTimeoutExecutorService(
    int poolSize, long keepAliveTime, TimeUnit timeUnit) 
{ 
    ThreadPoolExecutor e = 
     new ThreadPoolExecutor(poolSize, poolSize, 
      keepAliveTime, timeUnit, new LinkedBlockingQueue<Runnable>()); 
    e.allowCoreThreadTimeOut(true); 
    return e; 
} 

संपादित टिप्पणियों में की गयी टिप्पणी का जिक्र करते हुए: ध्यान दें कि यह थ्रेड पूल निष्पादक स्वचालित रूप से आवेदन बाहर निकलता है बंद नहीं होगा। एप्लिकेशन बाहर निकलने के बाद निष्पादक जारी रहेगा, लेकिन keepAliveTime से अधिक नहीं है। यदि, सटीक आवेदन आवश्यकताओं के आधार पर, keepAliveTime को कुछ सेकंड से अधिक समय तक होना चाहिए, answer by Pshemo में समाधान अधिक उपयुक्त हो सकता है: जब थ्रेड डिमन थ्रेड के रूप में सेट होते हैं, तो जब एप्लिकेशन निकलता है तो वे तत्काल समाप्त हो जाएंगे।

+0

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

+1

@Pshemo हां, यह 'शटडाउन' विधि में अर्थ में "शट डाउन" नहीं है। मैंने इसे थोड़ा सा बताया, उम्मीद है कि अब यह कम अस्पष्ट है। – Marco13

+0

@Pshemo आपकी उदारता के लिए धन्यवाद। एक ही विधि को कॉल करने के संकेत के लिए यह बहुत ध्यान है ;-) – Marco13

10

मैं गुवा के थ्रेडफैक्टरीबिल्डर वर्ग का उपयोग करूंगा।

ExecutorService threadPool = Executors.newFixedThreadPool(THREADS, new ThreadFactoryBuilder().setDaemon(true).build()); 

आप पहले से ही अमरूद उपयोग नहीं कर रहे हैं, मैं Pshemo's answer

+1

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

+3

यह अधिक संक्षिप्त है। यदि आप पहले ही गुवा का उपयोग कर रहे हैं, तो पुस्तकालय में मौजूद कोड को फिर से लिखना क्यों? आप सही हैं कि यह वही काम करता है। –

-1

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

जब आपका मुख्य धागा पूरा हो जाता है, तो सबमिट किए गए कार्यों को पूरा करने के लिए समय की अनुमति देने के लिए awaitTermination() विधि का उपयोग करें। वर्तमान में सबमिट किए गए कार्यों को निष्पादित किया जाएगा, और थ्रेड पूल पूरा होने के बाद अपने नियंत्रण धागे को समाप्त कर देगा।

for (Runnable task : tasks) { 
    threadPool.submit(task); 
} 
threadPool.shutdown(); 
/*... do other stuff ...*/ 
//All done, ready to exit 
while (!threadPool.isTerminated()) { 
    //this can throw InterruptedException, you'll need to decide how to deal with that. 
    threadPool.awaitTermination(1,TimeUnit.SECOND); 
} 
+1

यह रणनीति 'बाधित होने तक चलने वाले' पैटर्न का पालन करने वाले कार्यों को बाधित/रोक नहीं पाएगी, जिसमें थ्रेड चलते रहेंगे (क्योंकि वे डिमन नहीं हैं और बाधित नहीं हैं)। थ्रेड को डिमन पर सेट करना अधिक सुरक्षित है यदि वास्तव में उन्हें रोकना महत्वपूर्ण है। – Krease