15

いくつかのタスクを送信してから、すべての結果が利用可能になるまでそれらを待つ必要があります。それぞれがにを追加しStringますVector(デフォルトで同期されます)。次に、Vectorの結果ごとに新しいタスクを開始する必要がありますが、これを行う必要があるのは、前のすべてのタスクがジョブの実行を停止した場合のみです。

Java Executorを使用したいのですが、特にExecutors.newFixedThreadPool(100)固定数のスレッドを使用するために使用しようとしました(10または500の可変数のタスクがあります)が、executorを初めて使用するため、方法がわかりません。タスクの終了を待ちます。これは、私のプログラムが実行する必要があることの擬似コードのようなものです。

ExecutorService e = Executors.newFixedThreadPool(100);
while(true){

/*do something*/

for(...){
<start task>
}

<wait for all task termination>

for each String in result{
<start task>
}

<wait for all task termination>
}

しばらくしていて(true)、再利用する必要があるため、e.shutdownを実行できませんexecutorService...

手伝って頂けますか?Javaエグゼキュータに関するガイド/本を提案してもらえますか?

4

5 に答える 5

22

ExecutorService、複数のタスクを同時に実行し、Futureオブジェクトのコレクションを取り戻すメカニズムを提供します(タスクの非同期計算を表します)。

Collection<Callable<?>> tasks = new LinkedList<Callable<?>>();
//populate tasks
for (Future<?> f : executorService.invokeAll(tasks)) { //invokeAll() blocks until ALL tasks submitted to executor complete
    f.get(); 
}

Runnablesの代わりにsがある場合は、次の方法を使用してaをaにCallable簡単に変換できます。RunnableCallable<Object>

Callable<?> c = Executors.callable(runnable);
于 2009-08-24T12:48:05.483 に答える
14

Javaエグゼキュータに関するガイド/本を教えてもらえますか?

私はこの部分に答えることができます:

Brian Goetz(Tim Peierls、 Joshua Bloch、Joseph Bowbeer、David Holmes、 Doug Lea )によるJava同時実行が最善の策である可能性があります。

ただし、エグゼキュータだけでなくjava.util.concurrent、パッケージ全般、基本的な同時実行の概念と手法、およびJavaメモリモデルなどの高度なトピックについても説明します。

于 2009-08-24T12:52:43.860 に答える
14

RunnablesまたはCallablesをExecutor直接送信して対応するFuture戻り値を保存するのではなく、実装を使用して、完了時にCompletionServiceそれぞれを取得することをお勧めします。このアプローチは、タスクの生成を完了したタスクの消費から切り離し、たとえば、新しいタスクを一定期間にわたってプロデューサースレッドで開始できるようにします。Future

Collection<Callable<Result>> workItems = ...
ExecutorService executor = Executors.newSingleThreadExecutor();
CompletionService<Result> compService = new ExecutorCompletionService<Result>(executor);

// Add work items to Executor.
for (Callable<Result> workItem : workItems) {
  compService.submit(workItem);
}

// Consume results as they complete (this would typically occur on a different thread).
for (int i=0; i<workItems.size(); ++i) {
  Future<Result> fut = compService.take(); // Will block until a result is available.
  Result result = fut.get(); // Extract result; this will not block.
}
于 2009-08-24T13:03:15.330 に答える
2

エグゼキュータサービスにサブミットすると、Futureオブジェクトが返されます。

これらのオブジェクトをコレクションに格納してから、それぞれに対してget()を順番に呼び出します。get()基になるジョブが完了するまでブロックします。その結果、get()基になるすべてのジョブが完了すると、それぞれの呼び出しが完了します。

例えば

Collection<Future> futures = ...
for (Future f : futures) {
   Object result = f.get();
   // maybe do something with the result. This could be a
   // genericised Future<T>
}
System.out.println("Tasks completed");

これらがすべて完了したら、2回目の提出を開始します。スレッドプールは休止状態になり、再入力するため、これはスレッドプールの最適な使用法ではない可能性があることに注意してください。可能であれば、何かをするのに忙しくしてください。

于 2009-08-24T12:44:58.960 に答える
1
ExecutorService executor = ...
//submit tasks
executor.shutdown(); // previously submitted tasks are executed, 
                     // but no new tasks will be accepted
while(!executor.awaitTermination(1, TimeUnit.SECONDS))
    ;

カスタムExecutorServiceを作成せずに、やりたいことを簡単に行う方法はありません。

于 2010-04-06T13:28:32.367 に答える