2009-08-04 19 views
5

मैं एक कक्षा की तलाश में हूं जहां मैं काम करने के लिए एक विधि को ओवरराइड कर सकता हूं, और परिणामों को एक पुनरावर्तक की तरह वापस कर सकता हूं। कुछ इस तरह:जावा समांतर काम इटरेटर?

ParallelWorkIterator<Result> itr = new ParallelWorkIterator<Result>(trials,threads) { 

    public Result work() { 
    //do work here for a single trial... 
    return answer; 
    } 

}; 
while (itr.hasNext()) { 
    Result result = itr.next(); 
    //process result... 
} 

यह मुख्य रूप से मोंटे कार्लो सिमुलेशन जैसी चीजों के लिए इस्तेमाल किया जा रहा है, लेकिन मैं धागा पूल की स्थापना और लौटने धागे हर बार प्रबंधन के साथ सौदा करने के लिए नहीं करना चाहती। मैंने अपनी खुद की कक्षा को लुढ़काया कि उम्मीद है कि इसे पूरा करता है, लेकिन मुझे इसमें पर्याप्त भरोसा नहीं है और मैंने सोचा कि मैं यह जांचूंगा कि ऐसा कुछ पहले से मौजूद है या नहीं।

संपादित करें: स्पष्ट होने के लिए, मैं चाहता हूं कि यह पृष्ठभूमि में चलना जारी रखें और प्रत्येक कार्य विधि पूर्ण होने तक प्रत्येक कार्य विधि लौटाए जाने के बाद परिणाम प्राप्त करें। तो अगली विधि कतार में नतीजा होने तक लौटने की प्रतीक्षा कर सकती है।

उत्तर

12

ExecutorCompletionService पर एक नज़र डालें। यह सब कुछ आप चाहते हैं।

void solve(Executor e, Collection<Callable<Result>> solvers) 
    throws InterruptedException, ExecutionException { 
     //This class will hold and execute your tasks 
     CompletionService<Result> ecs 
      = new ExecutorCompletionService<Result>(e); 
     //Submit (start) all the tasks asynchronously 
     for (Callable<Result> s : solvers) 
      ecs.submit(s); 
     //Retrieve completed task results and use them 
     int n = solvers.size(); 
     for (int i = 0; i < n; ++i) { 
      Result r = ecs.take().get(); 
      if (r != null) 
       use(r); 
     } 
    } 

एक पूर्ण सेवा का उपयोग करने का लाभ यह है कि यह हमेशा पहले पूर्ण परिणाम देता है। यह सुनिश्चित करता है कि आप कार्यों को पूरा करने की प्रतीक्षा नहीं कर रहे हैं और यह पृष्ठभूमि में अपूर्ण कार्यों को चलाने देता है।

+0

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

+3

वर्बोज़ और अस्पष्ट एक डबल धार वाली तलवार का आधा हिस्सा है। –

+0

वर्बोजिटी को संभालने के लिए मैंने जो किया वह एक रैपर वर्ग लिखता है जो एक्जिक्यूटर्स कॉम्प्लिशन सेवा प्रदान करता है, और सबमिट किए गए फ़्यूचर्स की एक सूची रखता है। एक सार्वजनिक बूलियन है() {वापसी 0 Tim

2

मैं जावा Executors पर देखने की अनुशंसा करता हूं।

आप कई कार्यों को सबमिट करते हैं और प्रत्येक के लिए Future ऑब्जेक्ट वापस प्राप्त करते हैं। आपके काम को पृष्ठभूमि में संसाधित किया जाता है, और आप भविष्य की वस्तुओं के माध्यम से पुनरावृत्त होते हैं (जैसे आप ऊपर में करते हैं)।

1

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

सरल उदाहरण:

ExecutorService executor = Executors.newSingleThreadExecutor(); // Create vanilla executor service. 
CompletionService<Result> completionService = new ExecutorCompletionService<Result>(executor); // Completion service wraps executor and is notified of results as they complete. 
Callable<Result> callable = new MyCallable(); 

executor.submit(callable); // Do not store handle to Future here but rather obtain from CompletionService when we *know* the result is complete. 

Future<Result> fut = completionService.take(); // Will block until a completed result is available. 
Result result = fut.get(); // Will not block as we know this future represents a completed result. 

मैं Futureget() विधि दो संभावित जांचे हुए अपवादों फेंक कर सकते हैं के रूप में एक Iterator इंटरफ़ेस के पीछे इस लपेटकर की सिफारिश नहीं होगा: ExecutionException और InterruptedException, और इसलिए आप को पकड़ने के लिए और या तो निगल की आवश्यकता होगी इन्हें या RuntimeException के रूप में पुनर्स्थापित करें, इनमें से कोई भी बहुत अच्छी बात नहीं है। इसके अतिरिक्त, Iterator के hasNext() या next() विधियों को संभावित रूप से ब्लॉक करने की आवश्यकता होगी यदि प्रगति पर कोई कार्य था, जिसे Iterator का उपयोग कर ग्राहकों के लिए counterintuitive माना जा सकता है। इसके बजाय मैं अपने स्वयं के अधिक वर्णनात्मक इंटरफ़ेस को लागू करूंगा; जैसे

public interface BlockingResultSet { 
    /** 
    * Returns next result when it is ready, blocking is required. 
    * Returns null if no more results are available. 
    */ 
    Result take() throws InterruptedException, ExecutionException; 
} 

(तरीके कहा जाता take() आम तौर पर java.util.concurrent पैकेज में एक अवरुद्ध कॉल प्रतिनिधित्व करते हैं)।