2012-11-01 36 views
12

का उपयोग कर भविष्य के निर्माण की सूची के लिए कैसे प्रतीक्षा करें, इसलिए मुझे पता है कि यहां पहला उत्तर/टिप्पणी होगी "एक ExecutorService का उपयोग करें और invokeAll का उपयोग करें"। हालांकि, थ्रेड पूल को अलग रखने के लिए एक अच्छा कारण है (जिसे मैं लोगों के साथ नहीं बोलेगा)।विभिन्न 'निष्पादक सेवा'

तो मैं एक (ExecutorServices) धागा पूल की सूची और क्या मैं (कोई समस्या नहीं) प्रत्येक थ्रेड पूल submit का उपयोग करने पर एक अलग Callable आह्वान करने की जरूरत है की है। अब मैं Future उदाहरणों, एक अलग ExecutorService पर बनाए गए प्रत्येक के इस संग्रह है, और मुझे उन सभी को (और समय समाप्त, जिस पर नहीं किया किसी भी रद्द कर देने में सक्षम हो) को पूरा करने के लिए इंतजार करना चाहते हैं।

क्या कोई मौजूदा वर्ग है जो ऐसा करेगा (Future उदाहरणों की एक सूची लपेटें और सभी प्रतीक्षा किए जाने तक प्रतीक्षा करें)? यदि नहीं, तो एक कुशल तंत्र पर सुझावों की सराहना की जाएगी।

प्रत्येक के लिए एक समय समाप्ति के साथ get बुला के बारे में सोच रहा था, लेकिन कुल समय प्रत्येक कॉल के लिए पारित कर दिया की एक गणना करना है।

मैंने यह पोस्ट Wait Until Any of Future is Done देखा लेकिन यह उनकी सूची को लपेटने के बजाय Future बढ़ाता है।

+0

प्रत्येक सूची के लिए और जब आखिरी व्यक्ति किया जाता है - जैसा कि वे कहते हैं –

+0

अपडेट किया गया पोस्ट यह स्पष्ट करने के लिए कि टाइमआउट यह मुद्दा है और मैं उस संबंध में पहिया को फिर से नहीं खोलने की उम्मीद कर रहा हूं। –

+0

अच्छी तरह से यदि आप उन निफ्टी लिल 'जावा डॉक्स को पढ़ते हैं तो आप देखेंगे कि आप प्रतीक्षा कर सकते हैं और जब आप अपना कार्य सबमिट करते हैं तो टाइमआउट सेट कर सकते हैं तो आप इसे बंद कर सकते हैं और यदि कार्य समय पर पूरा नहीं होता है तो यह आपके टाइमआउट के बाद खराब हो जाता है! !!! –

उत्तर

16

प्रति लुईस की टिप्पणी, मैं के लिए क्या देख रहा था था Futures.successfulAsList

यह (कुछ कैप्सूलीकरण समय और स्थान के लिए छोड़े गए) मुझे पूरा करने के लिए इंतजार करने की अनुमति देता है और फिर असफल होने वाले किसी भी वायदा की जांच करता है।

अमरूद नियम!

2

मुझे नहीं लगता कि JDK आप ऐसा कर सकते है कि एक सीधा एपीआई प्रदान करता है। हालांकि, मुझे लगता है कि यह एक सरल विधि बनाने के लिए समान रूप से सरल है जो ऐसा करता है। आप यह विचार प्राप्त करने के लिए AbstractExecutorService.invokeAll() के कार्यान्वयन पर एक नज़र डालना चाहते हैं कि यह किया जा सकता है।

अनिवार्य रूप से, आप प्रत्येक भविष्य पर future.get() को कॉल करेंगे, प्रत्येक बार परिणाम की प्रतीक्षा करने के लिए प्रतीक्षा समय घटाना होगा, और विधि से लौटने से पहले सभी बकाया वायदा रद्द करें।

+0

+1 Concur। मैंने इसके बारे में सोचा था और इसे स्पष्ट तंत्र के रूप में अपनी पोस्ट में शामिल किया था। मैं उम्मीद कर रहा था कि एक बेहतर/पहले से ही लागू तंत्र था और किसी और को पता था। –

+0

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

1

हो सकता है कि मैं वास्तव में यह नहीं मिला। हालांकि, मेरे लिए यह अभी भी

public <V> List<V> get(List<Future<V>> futures, long timeout, TimeUnit unit) 
      throws InterruptedException, ExecutionException, TimeoutException { 
    List<V> result = new ArrayList<V>(); 
    long end = System.nanoTime() + unit.toNanos(timeout); 
    for (Future<V> f: futures) { 
     result.add(f.get(end - System.nanoTime(), TimeUnit.NANOSECONDS)); 
    } 
    return result; 
} 

क्या मैं इसके साथ गलत लगता हूं?

सवाल आप लिंक और अधिक जटिल मुझे लगता है, है के रूप में वे केवल सबसे तेजी के लिए इंतजार करना चाहते हैं, और निश्चित रूप से पता नहीं है जो सबसे तेजी से होगा।

+0

+1 इसके साथ समस्या यह है कि 'get' अपवाद फेंक सकता है। इसे पूरा करने के बाद 'फ्यूचर्स' वापस करने के लिए इसे बदलना मदद करेगा। इसके अलावा, यह शट डाउन को संभाल नहीं करता है। यह स्पष्ट कार्यान्वयन है, मैं यह देखना चाहता था कि परीक्षण के रूप में कुछ क्लीनर/पहले ही लागू किया गया था या नहीं। –

1

यह कुछ सफाई इस्तेमाल कर सकते हैं, लेकिन यह आपकी समस्या का समाधान करना चाहिए।

public static <T> LatchWithWrappedCallables<T> wrapCallables(Collection<Callable<T>> callablesToWrap) 
{ 
    CountDownLatch latch = new CountDownLatch(callablesToWrap.size()); 
    List<Callable<T>> wrapped = new ArrayList<Callable<T>>(callablesToWrap.size()); 
    for (Callable<T> currCallable : callablesToWrap) 
    { 
     wrapped.add(new CallableCountdownWrapper<T>(currCallable, latch)); 
    } 

    LatchWithWrappedCallables<T> returnVal = new LatchWithWrappedCallables<T>(); 
    returnVal.latch = latch; 
    returnVal.wrappedCallables = wrapped; 
    return returnVal; 
} 

public static class LatchWithWrappedCallables<T> 
{ 
    public CountDownLatch latch; 
    public Collection<Callable<T>> wrappedCallables; 
} 

public static class CallableCountdownWrapper<T> implements Callable<T> 
{ 
    private final Callable<T> wrapped; 

    private final CountDownLatch latch; 

    public CallableCountdownWrapper(Callable<T> wrapped, CountDownLatch latch) 
    { 
     this.wrapped = wrapped; 
     this.latch = latch; 
    } 

    @Override 
    public T call() throws Exception 
    { 
     try 
     { 
      return wrapped.call(); 
     } 
     finally 
     { 
      latch.countDown(); 
     } 
    } 
} 

फिर अपने कोड इस तरह यह कहेंगे:

Collection<Callable<String>> callablesToWrap = [Your callables that you need to wait for here]; 
LatchWithWrappedCallables<String> latchAndCallables = wrapCallables(callablesToWrap); 

[Submit the wrapped callables to the executors here] 

if(latchAndCallables.latch.await(timeToWaitInSec, TimeUnit.SECONDS)) 
{ 
    [Handling for timeout here] 
} 
+0

और दूसरे विचार पर, मुझे लगता है कि मैं संभवतः लचविथप्रैपड कैलेबल्स क्लास में सीधे इंतजार कर सकता हूं ताकि इसे और भी आसान बना दिया जा सके। (और हाँ, "LatchWithWrappedCallables" एक भयानक नाम है!) –

+0

मैं यह देखने के लिए कल कुछ गहरा विचार दूंगा कि यह मेरी आवश्यकताओं के अनुरूप है या नहीं। धन्यवाद। –

+0

अच्छा। मुझे सुनने योग्य भविष्य की चीज़ भी देखना है। –