2009-09-01 8 views
29

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

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

मैंने ऐसा करने के कई तरीकों के बारे में सोचा है, लेकिन वे सभी अत्यधिक जटिल लगते हैं। मैं उम्मीद कर रहा था कि वहां कुछ विधि होगी जो धागे के समूह को पूरा करने की प्रतीक्षा कर सकती है। क्या ऐसा कुछ भी मौजूद है?

धन्यवाद।

+0

संभावित डुप्लिकेट [थ्रेड के सेट के लिए कैसे प्रतीक्षा करें?] (Http://stackoverflow.com/questions/ 12521 9 0/कैसे-के-प्रतीक्षा-के-सेट-ऑफ-थ्रेड-टू-पूर्ण) –

उत्तर

49

बस उन्हें एक के बाद एक में शामिल होने:

for (Thread thread : threads) { 
    thread.join(); 
} 

(आप InterruptedException साथ कुछ करने की आवश्यकता होगी, और आप अच्छी तरह से कोई बात बिगड़ जाए मामले में एक टाइम-आउट प्रदान करने के लिए चाहते हो सकता है, लेकिन है कि बुनियादी है विचार ...)

+0

धन्यवाद, ऐसा लगता है, यह मेरे क्लीनअप विधि में थ्रेड संदर्भ प्राप्त करने के लिए मेरे कोड को थोड़ा सा रिफैक्टर करना था, लेकिन मुझे लगता है कि यह काम कर रहा है। यह अभी चल रहा है, बस कुछ मिनट लेता है। –

+0

बस इसे पूरा करने के लिए पूरा किया। पूरी तरह से काम किया। –

+8

@ जोन स्कीट, मुझे एक संदेह है। लाइन 'thread.join(); 'थ्रेड' थ्रेड 'चलने तक प्रतीक्षा करने के लिए वर्तमान प्रक्रिया करेगा, है ना? तो यहां क्या होगा, मुख्य प्रक्रिया दूसरी पंक्ति में आ जाएगी और 'थ्रेड' के काम को पूरा करने के लिए इंतजार करेगी, फिर यह लूप में अगले 'थ्रेड' के लिए जाएगी, इसलिए वास्तव में मुख्य बच्चा थ्रेड चलने तक इंतजार करेगा, तो यह अगले थ्रेड के लिए 'thread.join()' निष्पादित करेगा, क्या मैं सही हूँ? – Patriks

8

एक उपयोगिता विधि को परिभाषित करें (या विधि) अपने आप को:

public static waitFor(Collection<? extends Thread) c) throws InterruptedException { 
    for(Thread t : c) t.join(); 
} 

या आप एक सरणी

हो सकता है
public static waitFor(Thread[] ts) throws InterruptedException { 
    waitFor(Arrays.asList(ts)); 
} 

वैकल्पिक रूप से आप java.util.concurrent पुस्तकालय में एक CyclicBarrier का उपयोग कर एक से अधिक थ्रेड के बीच स्वेच्छाचारी मुलाकात बिंदु को लागू करने पर दिखाई दे सकता है।

14

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

+0

धन्यवाद, ऐसा लगता है कि यह वही करेगा जो मैं चाहता हूं लेकिन जब मैंने इसे देखा तो जॉन के जवाब को पहले से ही लिखा था। –

+2

एक विकल्प, यदि आप केवल एक बार ऐसा कर रहे हैं, तो उलटी गिनती का उपयोग करना है। –

5

क्या आपने कक्षाओं को java.util.concurrent में देखा है? आप अपने धागे को ExecutorService के माध्यम से चला सकते हैं। यह आपको एक एकल वस्तु देता है जिसका उपयोग आप धागे को रद्द करने या पूरा करने के लिए प्रतीक्षा करने के लिए कर सकते हैं।

1

आप (एक ExecutorService को प्रस्तुत करने) धागे के निर्माण पर नियंत्रण है तो यह आप उपयोग कर सकते हैं एक ExecutorCompletionService वहाँ विभिन्न जवाब के लिए ExecutorCompletionService? Why do need one if we have invokeAll? देख प्रतीत होता है।

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

आप यह कुछ इस तरह का उपयोग करेंगे:

JoinThreads join = new JoinThreads(threads); 
for(int i = 0; i < threads.size(); i++) { 
    Thread justJoined = join.joinNextThread(); 
    System.out.println("Done with a thread, just joined=" + justJoined); 
} 

और स्रोत:

public static class JoinThreads { 
    java.util.concurrent.LinkedBlockingQueue<Thread> doneThreads = 
     new LinkedBlockingQueue<Thread>(); 

    public JoinThreads(List<Thread> threads) { 
    for(Thread t : threads) { 
     final Thread joinThis = t; 
     new Thread(new Runnable() { 
     @Override 
     public void run() { 
      try { 
      joinThis.join(); 
      doneThreads.add(joinThis); 
      } 
      catch (InterruptedException e) { 
      // "should" never get here, since we control this thread and don't call interrupt on it 
      } 
     } 
     }).start(); 
    } 

    } 

    Thread joinNextThread() throws InterruptedException { 
    return doneThreads.take(); 
    } 
} 

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