0

私はJavaエグゼキュータを使用して、特定のタスクを並列に分割して処理しています。タスクはいくつあってもかまいません。それらはすべて最初にキューに入れられ、マスターコントローラーオブジェクトは単にそれらすべてが終了するのを待ちます。

私が直面している問題は、すべてのタスクがいつ完了したかを判断する方法です。1つの大きなタスクは一度にすべてのキューに入れられるだけなので(つまり、現在キューに入れられているすべてのタスクはすべて同じマスタータスクに属します)、このgetCompletedTaskCount()メソッドを使用して、完了したタスクの数を最初にキューに入れられたタスクの数と比較できます。

ただし、これには、完了したタスクの数についてエグゼキュータを常にポーリングする必要があり、私の意見では、それほど優れた解決策ではありません。

while (pool.getCompletedTaskCount() - start_count < num_tasks)
{
    try
    {
        Thread.sleep(30);
    }
    catch (InterruptedException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

各タスクがインクリメントできるカウンターオブジェクトを用意することを考えました。カウントが予想されるタスクの数と等しい場合は、マスタースレッドに通知します。このようなもの(例外ハンドラーの欠落などのやや不完全なコードは無視してください):

マスタースレッド:

counter_object.expected_count = num_tasks;
counter_object.count = 0;
queue_tasks();
synchronized(counter_object)
{
    counter_object.wait();
}
// all tasks have finished

ワーカータスク:

// ...do task
// task finished, update counter
synchronized(counter_object)
{
    ++counter_object.count;
    if(counter_object.count == counter_object.expected_count)
    {
        // all tasks have finished, notify master thread
        counter_object.notify();
    }
}

このメソッドには、カウンターオブジェクトが特定のマスターに対してローカルであるため、単一のエグゼキューターを使用して複数のマスタータスクを実行できるという追加の利点もあります。

この問題を解決するためのより良い方法はありますか?タスクの数は、エグゼキュータが作成できるスレッドの最大数よりもかなり多い可能性があるため、 CyclicBarrierは機能しないと思います。

4

1 に答える 1

2

これはExecutorService.invokeAllの仕事のように聞こえます。

Collection<Callable> tasks = <get all sub tasks>;
executorService.invokeAll(tasks);
// Execution proceeds at the following line only once all "tasks" have been run

または(インスタンスを処理している可能性があり、Runnableインスタンスを処理していない可能性があるCallableため、を使用ExecutorService.submit(Runnable)して、インスタンスが完了するのを待つことができます。

for (Runnable task:tasks) {
    futures.add(executorService.submit(task));
}

for (Future<Void> result:futures) {
    result.get();
}

注:例外処理は省略されています

于 2012-10-09T00:44:28.327 に答える