ExecutorServiceを使用して、すべてのスレッドが完了するのを待つ方法は?


381

次のように、一度にいくつかのタスクを4回実行する必要があります。

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

それらがすべて完了したら、どうすれば通知を受け取ることができますか?今のところ、いくつかのグローバルタスクカウンターを設定し、すべてのタスクの終わりにそれを減らすことよりも良いことを考えることはできません。その後、無限ループでこのカウンターを監視して0にします。または、Futureのリストを取得し、それらすべてに対して無限ループモニターisDoneを実行します。無限ループを含まないより良い解決策は何ですか?

ありがとう。

回答:


446

基本的には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) {
  ...
}

9
これは、shutdown / awaitTerminationが意図するものです
matt b

31
このタスク処理が1回限りのイベントである場合は、これは良いパターンです。ただし、同じランタイム中に繰り返し実行される場合は、実行されるたびにスレッドを繰り返し作成および破棄するため、最適ではありません。
sjlee 09

44
Long.MAX_VALUE, TimeUnit.NANOSECONDSタイムアウトがないことに相当する公式ドキュメントを探しています。
サム・ハーウェル

15
現在のすべてのスレッドに参加するには、shutdownを使用する必要があるとは思えません(shutdownを使用した後は、executorを再び使用することはできません)。代わりにフューチャーのリストを使用することをお
勧めし

20
参照@SamHarwell java.util.concurrentパッケージのマニュアルを参照して下のTimingセクション:「永遠」を待つために、あなたがの値を使用することができますLong.MAX_VALUE
beluchin

174

CountDownLatchを使用します。

CountDownLatch latch = new CountDownLatch(totalNumberOfTasks);
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
  taskExecutor.execute(new MyTask());
}

try {
  latch.await();
} catch (InterruptedException E) {
   // handle
}

そしてあなたのタスク内(try / finallyで囲む)

latch.countDown();

3
4つのタスクはありません。「いくつかのタスク」は一度に4つ実行されます。
cletus 2009

2
すみません、質問を誤解しました。はい、タスクの数はCountDownLatchコンストラクターの引数にする必要があります
ChssPly76

3
このソリューションは他のソリューションよりもエレガントで、この目的のために作成されたようであり、シンプルで簡単です。
wvdschel 2009

3
開始する前にタスクの数がわからない場合はどうなりますか?
cletus 2009

11
@cletus-次に、CountDownLatchを使用しないでください:-)気を付けてください。このアプローチがあなたのアプローチより優れているとは主張していません。ただし、実際のシナリオで、タスクの数わかっています、スレッドプールの設定展開ごとに構成可能である必要があり、プール再利用できます。だから私は通常、Springによってスレッドプールを挿入し、それらをプロトタイプとして設定し、スレッドが完了するのを待つためだけに手動でシャットダウンして、理想的とは言えない ように思えます。
ChssPly76 09

82

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);

難易度は、一度に「4」のスレッドを1つずつ起動したときに、区分的、そして/すべての4を終了させ...参加する場合/来る
rogerdpack

@rogerdpack:私はまだこのエグゼキューターとかを学んでいます。しかし、あなたの質問に応えて。一度に4つのスレッドを、上記の回答を使用して実行されるバッチタスクの一部にしないでください。
Mukul Goel

3
この方法は、事前にタスクの数がわかっている場合にのみ機能します。
コンスタンティン

3
私はときだと思いfutures返され、タスクが完了していません。それらは将来完了する可能性があり、結果へのリンクがあります。これがと呼ばれる理由Futureです。メソッドFuture.get()があり、タスクが終了して結果を取得するまで待機します。
AlikElzin-kilaka 2016年

5
@ AlikElzin-kilaka JavaDocsからの引用(回答にリンクされています):「指定されたタスクを実行し、すべての完了時にステータスと結果を保持するFutureのリストを返します。Future.isDone()は、返されたリストの各要素に対してtrueです。 」
ハルク

47

先物リストも使用できます。

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(); }

基本的に、トリックは、(すべてまたはそれぞれ)でisDone()を呼び出す無限ループの代わりに、Futureごとに.get()を一度に1つずつ呼び出すことです。したがって、最後のスレッドが終了するとすぐに、このブロックを通過してこのブロックを通過することが保証されます。注意点は、.get()呼び出しは例外を再発生させるため、スレッドの1つが停止した場合、他のスレッドが完了する前にこれから発生する可能性があります[これを回避するにcatch ExecutionExceptionは、get呼び出しの周りに追加することができます]。他の注意点は、すべてのスレッドへの参照を保持するため、スレッドローカル変数がある場合、このブロックを通過するまで収集されません(問題が発生した場合は、これを回避することで回避できます)今後はArrayListから外れます)。どのFutureが「最初に終了する」か知りたい場合https://stackoverflow.com/a/31885029/32453


3
「最初に終了する」ことを知るには、次を使用しますExecutorCompletionService.takestackoverflow.com/a/11872604/199364
ToolmakerSteve

34

Java8ではあなたがそれを行うことができますCompletableFuture

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();

3
これは非常にエレガントなソリューションです。
mattvonb 2018

ExecutorService es = Executors.newFixedThreadPool(4); List< Future<?>> futures = new ArrayList<>(); for(Runnable task : taskList) { futures.add(es.submit(task)); } for(Future<?> future : futures) { try { future.get(); }catch(Exception e){ // do logging and nothing else } }
user2862544 2018

@AdamSkywalkerは、es.shutdown()の後にawaitTermination()が必要ですか?
gaurav

@gauravでシャットダウンを呼び出すと、一部のタスクがまだ完了していない場合があります。したがって、awaitTerminationは、すべてが完了するまで呼び出しスレッドをブロックします。このスレッドで結果を待つ必要があるかどうかによって異なります。
AdamSkywalker

@AdamSkywalker素晴らしい答え。結果を待つ必要がない場合は、awaitTermination()を呼び出さないのが理にかなっています。
gaurav

26

ちょうど私の2セント。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()、あなたがそうするように電話するだけですlatch.countDown();


これを見て、私は最初にいくつかのrelease呼び出しが呼び出しの前に発生すると問題になるかどうか疑問に思いましたacquireが、Semaphoreのドキュメントを読んだ後、それで問題ありません。
ToolmakerSteve 2015

13

ゲームに少し遅れますが、完了のために...

すべてのタスクが完了するのを「待つ」のではなく、ハリウッドの原則として、「私に電話しないで、私はあなたに電話する」と考えることができます。結果のコードはよりエレガントだと思います...

グアバはこれを達成するためのいくつかの興味深いツールを提供しています。

例 ::

ExecutorServiceをListeningExecutorServiceにラップする::

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);
        }
    });

これには、処理が完了すると、すべての結果を1か所で収集できるという利点もあります...

詳細はこちら


2
非常にきれいな。Androidでも問題なく動作します。で使用する必要がありrunOnUiThread()ましたonSuccess()
DSchmidt 2017

12

Java 5以降のCyclicBarrierクラスは、この種のもののために設計されています。


7
このデータ構造の名前を覚えることはできません。ただし、キューに入れられるタスクの量が事前にわかっている場合にのみ適しています。
ᆼᆺᆼ

ええ、あなたは現在のスレッドとすべての子スレッドで障壁を打つことができると思います、そしてそれを渡すと、子スレッドが完了したことがわかります...
rogerdpack

実はそれは間違った答えです。部分のために設計されたCyclicBarrier。待機イベント用に設計されたCountDownLatch
gstackoverflow

7

以下のいずれかの方法に従います。

  1. から返されたすべてのFutureタスクを繰り返し、提案されたようにオブジェクトのブロック呼び出しでステータスを確認しますsubmitExecutorServiceget()FutureKiran
  2. 使用invokeAll()上のExecutorServiceの
  3. CountDownLatch
  4. ForkJoinPoolまたはExecutors.html#newWorkStealingPool
  5. shutdown, awaitTermination, shutdownNowThreadPoolExecutorのAPIを適切な順序で使用する

関連するSEの質問:

CountDownLatchはJavaマルチスレッドでどのように使用されますか?

Java ExecutorServiceを適切にシャットダウンする方法


6

ここに2つのオプションがありますが、どちらを使用するのが最善かを少し混乱させてください。

オプション1:

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();

オプション2:

ExecutorService es = Executors.newFixedThreadPool(4);
List< Future<?>> futures = new ArrayList<>();
for(Runnable task : taskList) {
    futures.add(es.submit(task));
}

for(Future<?> future : futures) {
    try {
        future.get();
    }catch(Exception e){
        // do logging and nothing else
    }
}
es.shutdown();

ここにfuture.get();を置きます。トライキャッチで良いアイデアですよね?


5

通知を送信する別の実行可能ファイルでタスクをラップできます。

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

1
これがOPの質問をどのように解決するかを確認するために、しばらく時間をかけました。まず、このラッピングはタスクのものであり、すべてのタスクを開始するコードではないことに注意してください。おそらく、開始ごとにカウンターが増分され、終了ごとにそのカウンターが減分されるか、completedカウンターが増分されます。したがって、それらをすべて開始した後、通知ごとに、すべてのタスクが完了したかどうかを判断できます。タスクが失敗した場合でもtry/finally完了通知(またはcatchブロック内の代替通知)が提供されるように使用することが重要です。そうでなければ、永遠に待ちます。
ToolmakerSteve

3

あなたの問題を解決するサンプルプログラムを書いたところです。簡潔な実装が指定されていなかったので、追加します。executor.shutdown()およびを使用することはできますがexecutor.awaitTermination()、さまざまなスレッドがかかる時間は予測不可能であるため、これはベストプラクティスではありません。

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();
    }

future.getの使用方法を示すのは良いことです。しかし、許容できる最大のタイムアウトを設定するよりも、永遠に待つ方がよいと考える理由は何ですか。さらに重要なのは、すべてのタスクが完了するまで(本質的には永遠に)待機したい場合、awaitTerminationに本当に非常に長い時間を与えることができる場合、このロジックをすべて実行する理由はありません。
ToolmakerSteve

これは、ここですでに提示されているソリューションと同じです。あなたの正しい解決策は、@ sjleeによって提示されたものと同じです
パルプフィクション

オラクルのドキュメントによると、なぜすべてを確認する必要があるのか​​わからないので、invokeAllは「すべてが完了するか、タイムアウトのいずれかが最初に発生したとき」のみを返す
Mashrur

3

ここで、ラッチ/バリアを使用するための別の選択肢を提供します。すべてがCompletionServiceを使用して完了するまで、部分的な結果を取得することもできます。

実際のJava同時実行性から:「Executorに送信する計算のバッチがあり、それらが利用可能になったときに結果を取得したい場合、各タスクに関連付けられたFutureを保持し、getを呼び出して完了を繰り返しポーリングすることができます。ゼロのタイムアウト。これは可能ですが、面倒です。幸い、もっと良い方法があります:完了サービスです。」

ここでの実装

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());
        }
    }
}

3

これは「AdamSkywalker」のヒントに基づいた私の解決策であり、機能します

package frss.main;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestHilos {

    void procesar() {
        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();

        System.out.println("FIN DEL PROCESO DE HILOS");
    }

    private List<Runnable> getTasks() {
        List<Runnable> tasks = new ArrayList<Runnable>();

        Hilo01 task1 = new Hilo01();
        tasks.add(task1);

        Hilo02 task2 = new Hilo02();
        tasks.add(task2);
        return tasks;
    }

    private class Hilo01 extends Thread {

        @Override
        public void run() {
            System.out.println("HILO 1");
        }

    }

    private class Hilo02 extends Thread {

        @Override
        public void run() {
            try {
                sleep(2000);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("HILO 2");
        }

    }


    public static void main(String[] args) {
        TestHilos test = new TestHilos();
        test.procesar();
    }
}

2

次のコードを使用できます。

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");

2

次の作業例を作成しました。アイデアは、多数のスレッド(numberOfTasks / thresholdによってプログラムで決定される)を使用してタスクのプール(例としてキューを使用しています)を処理し、すべてのスレッドが完了するまで待機して他の処理を続行する方法を持つことです。

import java.util.PriorityQueue;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/** Testing CountDownLatch and ExecutorService to manage scenario where
 * multiple Threads work together to complete tasks from a single
 * resource provider, so the processing can be faster. */
public class ThreadCountDown {

private CountDownLatch threadsCountdown = null;
private static Queue<Integer> tasks = new PriorityQueue<>();

public static void main(String[] args) {
    // Create a queue with "Tasks"
    int numberOfTasks = 2000;
    while(numberOfTasks-- > 0) {
        tasks.add(numberOfTasks);
    }

    // Initiate Processing of Tasks
    ThreadCountDown main = new ThreadCountDown();
    main.process(tasks);
}

/* Receiving the Tasks to process, and creating multiple Threads
* to process in parallel. */
private void process(Queue<Integer> tasks) {
    int numberOfThreads = getNumberOfThreadsRequired(tasks.size());
    threadsCountdown = new CountDownLatch(numberOfThreads);
    ExecutorService threadExecutor = Executors.newFixedThreadPool(numberOfThreads);

    //Initialize each Thread
    while(numberOfThreads-- > 0) {
        System.out.println("Initializing Thread: "+numberOfThreads);
        threadExecutor.execute(new MyThread("Thread "+numberOfThreads));
    }

    try {
        //Shutdown the Executor, so it cannot receive more Threads.
        threadExecutor.shutdown();
        threadsCountdown.await();
        System.out.println("ALL THREADS COMPLETED!");
        //continue With Some Other Process Here
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }
}

/* Determine the number of Threads to create */
private int getNumberOfThreadsRequired(int size) {
    int threshold = 100;
    int threads = size / threshold;
    if( size > (threads*threshold) ){
        threads++;
    }
    return threads;
}

/* Task Provider. All Threads will get their task from here */
private synchronized static Integer getTask(){
    return tasks.poll();
}

/* The Threads will get Tasks and process them, while still available.
* When no more tasks available, the thread will complete and reduce the threadsCountdown */
private class MyThread implements Runnable {

    private String threadName;

    protected MyThread(String threadName) {
        super();
        this.threadName = threadName;
    }

    @Override
    public void run() {
        Integer task;
        try{
            //Check in the Task pool if anything pending to process
            while( (task = getTask()) != null ){
                processTask(task);
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            /*Reduce count when no more tasks to process. Eventually all
            Threads will end-up here, reducing the count to 0, allowing
            the flow to continue after threadsCountdown.await(); */
            threadsCountdown.countDown();
        }
    }

    private void processTask(Integer task){
        try{
            System.out.println(this.threadName+" is Working on Task: "+ task);
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }
}
}

それが役に立てば幸い!



1

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);
    }

}

shutdown()/の後にawaitTermination()が必要です
gaurav

1

だから私はここにリンクされた質問から私の答えを投稿します

ExecutorService executor = Executors.newFixedThreadPool(10);
CompletableFuture[] futures = new CompletableFuture[10];
int i = 0;
while (...) {
    futures[i++] =  CompletableFuture.runAsync(runner, executor);
}

CompletableFuture.allOf(futures).join(); // THis will wait until all future ready.

0

Java 8-ストリームAPIを使用してストリームを処理できます。以下のスニペットをご覧ください

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();

2
こんにちはVlad、StackOverflowへようこそ。これが質問にどのように答えるか、そしてコードが何をするかを説明するためにあなたの答えを編集できますか?ここではコードのみの回答はお勧めしません。ありがとうございました!
Tim Malone

この投稿では、同時実行性について説明します。並列処理!=同時実行性
GabrielBB

0

ExecutorService WORKER_THREAD_POOL 
  = Executors.newFixedThreadPool(10);
CountDownLatch latch = new CountDownLatch(2);
for (int i = 0; i < 2; i++) {
    WORKER_THREAD_POOL.submit(() -> {
        try {
            // doSomething();
            latch.countDown();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    });
}

// wait for the latch to be decremented by the two remaining threads
latch.await();

doSomething()他の例外をスローした場合latch.countDown()は実行されないようですので、どうすればよいですか?


0

より多くのスレッドExecutionServicesを順次使用し、各EXECUTIONSERVICEが完了するまで待機したい場合。最良の方法は以下のようなものです。

ExecutorService executer1 = Executors.newFixedThreadPool(THREAD_SIZE1);
for (<loop>) {
   executer1.execute(new Runnable() {
            @Override
            public void run() {
                ...
            }
        });
} 
executer1.shutdown();

try{
   executer1.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);

   ExecutorService executer2 = Executors.newFixedThreadPool(THREAD_SIZE2);
   for (true) {
      executer2.execute(new Runnable() {
            @Override
            public void run() {
                 ...
            }
        });
   } 
   executer2.shutdown();
} catch (Exception e){
 ...
}

-1

これは役立つかもしれません

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) {}
            }

-1

このRunnerクラスでwaitTillDone()を呼び出すことができます。

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

このクラスを再利用して、shutdown()を呼び出す前に何度でもwaitTillDone()を呼び出すことができます。さらに、コードは非常にシンプルです。また、事前にタスクを知っいる必要はありません

これを使用するには、このgradle / maven compile 'com.github.matejtymes:javafixes:1.3.1'依存関係をプロジェクトに追加するだけです。

詳細はここにあります:

https://github.com/MatejTymes/JavaFixes


-2

executorには、getActiveCount()アクティブなスレッドの数を示すメソッドがあります。

スレッドをスパンした後、activeCount()値がかどうかを確認できます0。値がゼロになると、現在実行中のアクティブなスレッドがないことを意味します。これは、タスクが終了したことを意味します。

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

3
良い考えではありません。stackoverflow.com / a / 7271685/1166992およびjavadocを参照してください:「アクティブにタスクを実行しているスレッドのおおよその数を返します。」
Olivier Faucheux 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.