6

私は3つFutureTask<T>のオブジェクトを持っています。それらが非同期で処理されることを望みます。ただし、FutureTasks のget()メソッドの 1 つが返されないとすぐnullに続行したいと思います。つまり、メソッド (ラッパー) が返され、他の 2 つの FutureTasks が処理されるまで待機しません。私は次のようなことを考えました:

private File wrapper(final File file) {
    ExecutorService executors = Executors.newCachedThreadPool();
    File returnFile;
    FutureTask<File> normal= ...
    FutureTask<File> medium=...     
    FutureTask<File> huge=...

    executors.execute(normal);
    executors.execute(medium);
    executors.execute(huge);
    try {
        if((returnFile=normal.get()) != null || 
           (returnFile=medium.get()) != null ||  
           (returnFile=huge.get()) != null)

            return returnFile;

    } catch(ExecutionException | InterruptedException e) { }
}

他の2つのタスクが完了するのを待たずに戻るだけなので、例外がスローされると想定しているため、(get()によってスローされた)例外を適切な方法でキャプチャする方法がわかりません。さらに、コードが意図したとおりに機能するかどうかは疑問です。私は解決策に近づいていると感じていますが、何かが欠けています。

4

2 に答える 2

1

FutureTask::isDone を確認することをお勧めしますか?

その場合、次のようになります。

while(true) {
    if (normal.isDone()) {
        return normal.get();
    }
    if (medium.isDone()) {
        return medium.get();
    }
    if (huge.isDone()) {
        return huge.get();
    }
}

編集: 1 つの結果が手元にあるとすぐに、他のタスクをキャンセルできます。

ドキュメントにはすでに次のように記載されているため、 FutureTask::getを使用すると、通常は常に normal.get() の結果が返される可能性が高いため、探しているものではありません。

必要に応じて計算が完了するまで待機し、その結果を取得します。

上記を明確にするには: FutureTask::get を使用する場合、get on を呼び出す最初の FutureTask はおそらくブロックされ、結果が返されるまで待機します。

EDIT2:

そのループを ExecutorService によって実行される新しい Runnable にラップし、利用可能な最初の結果を別のメソッドに渡すか、コールバックを実装すると、ビジー状態で待機する必要がなくなります。

于 2015-07-20T13:04:15.293 に答える