दिलचस्प पोस्ट
एएसपी एमवीसी 3 में एक दृश्य में दो मॉडल एक jQuery AJAX GET कॉल में अनुरोध हेडर पास करें Std :: function के साथ ओवरलोड संकल्प एक पायथन स्क्रिप्ट के भीतर से UAC उन्नयन का अनुरोध करें? एचटीएमएल 5 डेटा- * एस्प.net एमवीसी टेक्स्टबॉक्सफ्रेम HTML एट्रिब्यूट्स के साथ इकाई के लिए LINQ विधि 'System.Web.Mvc.FileResult' को नहीं पहचानता है महीना गणना का अंतिम दिन जावा में प्राइमटालिटी के लिए सबसे तेज़ तरीका क्या होगा? कैसे Ubuntu पर बढ़ावा देने के लिए स्थापित करें? वर्ण स्तंभ नाम से डेटा फ्रेम फ़िल्टर करें (dplyr में) क्या मैं Visual Studio 2008 में .NET 4.0 बीटा का उपयोग कर सकता हूं? खराब क्लास फ़ाइल जादू या संस्करण एंड्रॉइड ऐप अपडेट करें (Google Play के बिना) java.lang.NoClassDefFound त्रुटि: javax / servlet / jsp / jstl / core / कॉन्फ़िगरेशन वर्ड वर्ड बाय जावा में रिवर्स

निष्पादक सेवा का उपयोग कर, सभी थ्रेड्स को समाप्त करने के लिए कैसे प्रतीक्षा करें?

मुझे एक समय में कुछ 4 कार्य निष्पादित करने की आवश्यकता है, कुछ ऐसा:

ExecutorService taskExecutor = Executors.newFixedThreadPool(4); while(...) { taskExecutor.execute(new MyTask()); } //...wait for completion somehow 

एक बार जब वे सभी पूरा हो जाएंगे, तो मुझे कैसे सूचित किया जा सकता है? अभी के लिए मैं कुछ वैश्विक कार्य काउंटर सेट करने और प्रत्येक कार्य के अंत में इसे कम करने से बेहतर कुछ भी नहीं सोच सकता, फिर अनंत लूप में मॉनिटर 0 बनने के लिए इस काउंटर; या वायदा की एक सूची प्राप्त करें और अनंत लूप मॉनिटर में उन सभी के लिए है अनन्त लूपों को शामिल करने वाले बेहतर समाधान क्या हैं?

धन्यवाद।

Solutions Collecting From Web of "निष्पादक सेवा का उपयोग कर, सभी थ्रेड्स को समाप्त करने के लिए कैसे प्रतीक्षा करें?"

असल में एक ExecutorService आप shutdown() कॉल करते हैं और फिर awaitTermination() :

 ExecutorService taskExecutor = Executors.newFixedThreadPool(4); while(...) { taskExecutor.execute(new MyTask()); } taskExecutor.shutdown(); try { taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); } catch (InterruptedException e) { ... } 

काउंटडाउन लैच का प्रयोग करें:

 CountDownLatch latch = new CountDownLatch(totalNumberOfTasks); ExecutorService taskExecutor = Executors.newFixedThreadPool(4); while(...) { taskExecutor.execute(new MyTask()); } try { latch.await(); } catch (InterruptedException E) { // handle } 

और अपने कार्य के भीतर (अंत में / अंत में प्रयास करें)

 latch.countDown(); 

ExecutorService.invokeAll() आपके लिए यह करता है

 ExecutorService taskExecutor = Executors.newFixedThreadPool(4); List<Callable<?>> tasks; // your tasks // invokeAll() returns when all tasks are complete List<Future<?>> futures = taskExecutor.invokeAll(tasks); 

आप फ्यूचर्स की सूचियों का उपयोग भी कर सकते हैं:

 List<Future> futures = new ArrayList<Future>(); // now add to it: futures.add(executorInstance.submit(new Callable<Void>() { public Void call() throws IOException { // do something return null; } })); 

तब जब आप उन सभी में शामिल होना चाहते हैं, तो इसका अनिवार्य रूप से प्रत्येक पर शामिल होने के बराबर, (अतिरिक्त लाभ के साथ कि यह बाल थ्रेड्स से प्रमुख तक अपवाद उठाता है):

 for(Future f: this.futures) { f.get(); } 

असल में चाल को कॉल करना है (प्रत्येक या प्रत्येक) पर, अनंत लूपिंग कॉलिंग के बजाय, एक बार में प्रत्येक भविष्य पर कॉल करें। तो आपको "ब्लॉक ऑन" करने की गारंटी दी जाती है और इस ब्लॉक को पिछले थ्रेड समाप्त होने के साथ ही समाप्त कर दिया जाता है। चेतावनी यह है कि .get () कॉल अपवाद उठाता है, अगर एक धागा मर जाता है, तो आप संभवतः इस से पहले अन्य धागे को पूरा करने के लिए तैयार होंगे [इस से बचने के लिए, आप एक आस पास catch ExecutionException अपवाद जोड़ सकते हैं कॉल प्राप्त करें] अन्य चेतावनी यह सभी धागे के संदर्भ रखती है, इसलिए यदि उनके पास थ्रेड लोकल वैरिएबल हैं तो वे इस ब्लॉक (पिछले ब्लॉक करने के बाद तक एकत्र नहीं किए जाएंगे) (हालांकि आप इस समस्या को हल कर सकते हैं, यदि यह समस्या बन जाए भविष्य की अर्रेइस्ट बंद) यदि आप जानना चाहते हैं कि कौन सा भविष्य "पहले पूरा होगा" तो आप https://stackoverflow.com/a/31885029/32453 जैसे कुछ उपयोग कर सकते हैं

केवल मेरे दो सेंट्स। पहले से ही कार्यों की संख्या को जानने के लिए CountDownLatch की आवश्यकता को दूर करने के लिए, आप साधारण Semaphore का उपयोग करके इसे पुराने तरीके से कर सकते हैं

 ExecutorService taskExecutor = Executors.newFixedThreadPool(4); int numberOfTasks=0; Semaphore s=new Semaphore(0); while(...) { taskExecutor.execute(new MyTask()); numberOfTasks++; } try { s.aquire(numberOfTasks); ... 

आपके कार्य में बस s.release() को कॉल करें s.release() कि आप latch.countDown(); करेंगे। latch.countDown();

जावा 8 में आप इसे पूरी तरह से पूरा कर सकते हैं फ़्यूचर:

 ExecutorService es = Executors.newFixedThreadPool(4); List<Runnable> tasks = getTasks(); CompletableFuture<?>[] futures = tasks.stream() .map(task -> CompletableFuture.runAsync(task, es)) .toArray(CompletableFuture[]::new); CompletableFuture.allOf(futures).join(); es.shutdown(); 

जावा 5 और बाद के संस्करण में CyclicBarrier वर्ग इस प्रकार की चीज़ के लिए डिज़ाइन किया गया है

खेल को थोड़ा देर हो चुकी है लेकिन पूरा करने के लिए …

सभी कार्यों को समाप्त करने के लिए 'इंतजार' के बजाय, आप हॉलीवुड के सिद्धांत के संदर्भ में सोच सकते हैं, "मुझे कॉल मत करो, मैं आपको बुलाता हूं" – जब मैं समाप्त हो जाता हूं मुझे लगता है कि परिणामी कोड अधिक सुरुचिपूर्ण है …

यह पूरा करने के लिए गवावा कुछ दिलचस्प उपकरण प्रदान करता है

एक उदाहरण ::

एक सुनवाई एक्सक्लोरर सेवा में एक निष्पादक सेवा लपेटें ::

 ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10)); 

निष्पादन के लिए कॉलबल्स का एक संग्रह सबमिट करें ::

 for (Callable<Integer> callable : callables) { ListenableFuture<Integer> lf = service.submit(callable); // listenableFutures is a collection listenableFutures.add(lf) }); 

अब आवश्यक भाग:

 ListenableFuture<List<Integer>> lf = Futures.successfulAsList(listenableFutures); 

ListenableFuture को कॉलबैक संलग्न करें, जब आप सभी वायदा पूरा होने पर अधिसूचित होने के लिए उपयोग कर सकते हैं ::

  Futures.addCallback(lf, new FutureCallback<List<Integer>>() { @Override public void onSuccess(List<Integer> result) { log.info("@@ finished processing {} elements", Iterables.size(result)); // do something with all the results } @Override public void onFailure(Throwable t) { log.info("@@ failed because of :: {}", t); } }); 

यह भी लाभ प्रदान करता है कि प्रसंस्करण समाप्त हो जाने के बाद आप एक ही स्थान पर सभी परिणाम एकत्र कर सकते हैं …

अधिक जानकारी यहाँ

आप अपने कार्यों को एक और रननेबल में लपेट सकते हैं, जो सूचनाएं भेजेंगे:

 taskExecutor.execute(new Runnable() { public void run() { taskStartedNotification(); new MyTask().run(); taskFinishedNotification(); } }); 

मैंने सिर्फ एक नमूना कार्यक्रम लिखा है जो आपकी समस्या का समाधान करता है कोई संक्षिप्त क्रियान्वयन नहीं दिया गया था, इसलिए मैं एक जोड़ूंगा। जबकि आप executor.shutdown() और executor.awaitTermination() executor.shutdown() उपयोग कर सकते हैं, यह सर्वोत्तम अभ्यास नहीं है क्योंकि अलग-अलग थ्रेड्स द्वारा लिया गया समय अप्रत्याशित होगा।

 ExecutorService es = Executors.newCachedThreadPool(); List<Callable<Integer>> tasks = new ArrayList<>(); for (int j = 1; j <= 10; j++) { tasks.add(new Callable<Integer>() { @Override public Integer call() throws Exception { int sum = 0; System.out.println("Starting Thread " + Thread.currentThread().getId()); for (int i = 0; i < 1000000; i++) { sum += i; } System.out.println("Stopping Thread " + Thread.currentThread().getId()); return sum; } }); } try { List<Future<Integer>> futures = es.invokeAll(tasks); int flag = 0; for (Future<Integer> f : futures) { Integer res = f.get(); System.out.println("Sum: " + res); if (!f.isDone()) flag = 1; } if (flag == 0) System.out.println("SUCCESS"); else System.out.println("FAILED"); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } 

बस कुंडी / बाधाओं का उपयोग करने के लिए यहां अधिक विकल्प प्रदान करने के लिए आप अंशतः परिणाम प्राप्त कर सकते हैं जब तक कि वे सभी पूर्ण सेवा का उपयोग न करें।

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

यहां कार्यान्वयन

 public class TaskSubmiter { private final ExecutorService executor; TaskSubmiter(ExecutorService executor) { this.executor = executor; } void doSomethingLarge(AnySourceClass source) { final List<InterestedResult> info = doPartialAsyncProcess(source); CompletionService<PartialResult> completionService = new ExecutorCompletionService<PartialResult>(executor); for (final InterestedResult interestedResultItem : info) completionService.submit(new Callable<PartialResult>() { public PartialResult call() { return InterestedResult.doAnOperationToGetPartialResult(); } }); try { for (int t = 0, n = info.size(); t < n; t++) { Future<PartialResult> f = completionService.take(); PartialResult PartialResult = f.get(); processThisSegment(PartialResult); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (ExecutionException e) { throw somethinghrowable(e.getCause()); } } } 

निम्न दृष्टिकोणों में से एक का पालन करें

  1. सभी भविष्य के कार्यों के माध्यम से दोबारा, ExecutorService पर submit करने से वापस लौट आए और Future वस्तु पर अवरुद्ध कॉल get() करें get() साथ स्थिति की जांच करें जैसा कि Kiran द्वारा सुझाया गया है
  2. invokeAll() पर invokeAll() उपयोग करें
  3. CountDownLatch
  4. ForkJoinPool या निष्पादक। Html # newWorkStealingPool
  5. सही अनुक्रम में shutdown, awaitTermination, shutdownNow एपीआई का प्रयोग करें

संबंधित एसई प्रश्न:

कैसे जावा Multithreading में CountDownLatch उपयोग किया जाता है?

कैसे ठीक से बंद जावा निष्पादक सेवा

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

आपको executorService.shutdown() उपयोग करना चाहिए। executorService.shutdown() और executorService.awaitTermination

इस प्रकार एक उदाहरण है:

 public class ScheduledThreadPoolExample { public static void main(String[] args) throws InterruptedException { ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5); executorService.scheduleAtFixedRate(() -> System.out.println("process task."), 0, 1, TimeUnit.SECONDS); TimeUnit.SECONDS.sleep(10); executorService.shutdown(); executorService.awaitTermination(1, TimeUnit.DAYS); } } 

जावा 8 – हम स्ट्रीम को स्ट्रीम करने के लिए स्ट्रीम एपीआई का उपयोग कर सकते हैं। कृपया नीचे स्निपेट देखें

 final List<Runnable> tasks = ...; //or any other functional interface tasks.stream().parallel().forEach(Runnable::run) // Uses default pool //alternatively to specify parallelism new ForkJoinPool(15).submit( () -> tasks.stream().parallel().forEach(Runnable::run) ).get(); 

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

 public class MyTask implements Runnable { private CountDownLatch countDownLatch; public MyTask(CountDownLatch countDownLatch { this.countDownLatch = countDownLatch; } @Override public void run() { try { //Do somethings // this.countDownLatch.countDown();//important } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } } CountDownLatch countDownLatch = new CountDownLatch(NUMBER_OF_TASKS); ExecutorService taskExecutor = Executors.newFixedThreadPool(4); for (int i = 0; i < NUMBER_OF_TASKS; i++){ taskExecutor.execute(new MyTask(countDownLatch)); } countDownLatch.await(); System.out.println("Finish tasks"); 

यह मदद कर सकता है

 Log.i(LOG_TAG, "shutting down executor..."); executor.shutdown(); while (true) { try { Log.i(LOG_TAG, "Waiting for executor to terminate..."); if (executor.isTerminated()) break; if (executor.awaitTermination(5000, TimeUnit.MILLISECONDS)) { break; } } catch (InterruptedException ignored) {} } 

आप इस धावक वर्ग पर प्रतीक्षा अवधि () को कॉल कर सकते हैं:

 Runner runner = Runner.runner(4); // create pool with 4 threads in thread pool while(...) { runner.run(new MyTask()); // here you submit your task } runner.waitTillDone(); // and this blocks until all tasks are finished (or failed) runner.shutdown(); // once you done you can shutdown the runner 

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

इसका उपयोग करने के लिए बस इस compile 'com.github.matejtymes:javafixes:1.1.1' जोड़ें compile 'com.github.matejtymes:javafixes:1.1.1' आपके प्रोजेक्ट compile 'com.github.matejtymes:javafixes:1.1.1' निर्भरता।

अधिक विवरण यहां मिल सकता है:

https://github.com/MatejTymes/JavaFixes

http://matejtymes.blogspot.com/2016/04/executor-that-notifies-you-when-task.html

निष्पादक प्राप्त getActiveCount() में एक विधि है – जो सक्रिय धागे की गिनती देता है।

धागा फैले जाने के बाद, हम जांच सकते हैं कि activeCount() मान 0 । मान शून्य होने के बाद, इसका अर्थ है कि वर्तमान में कोई सक्रिय थ्रेड नहीं चल रहा है जिसका अर्थ है कि कार्य समाप्त हो गया है:

 while (true) { if (executor.getActiveCount() == 0) { //ur own piece of code break; } }