1

タスクを送信するスレッド プールを持つプロジェクトに取り組んでいます。各タスクはいわばチェーンです。タスクが実行されると、必要な処理が実行され、結果がチェックされます。これらの各タスクには、結果のマップ (単なる列挙型) と追加のタスクが含まれています。これらは同じスレッド内で呼び出され、タスクがなくなるまでサイクルが繰り返されます。タスクがなくなると、チェーンを遡って各結果をコレクションに追加し、それをメイン スレッドに返します。Q&D の例:

public abstract class MyCallable implements Callable<MyResponse> {

private Map<ResponseEnum, List<MyCallable>> callbacks;

public List<MyResponse> call() {
    List<MyResponse> resp = new ArrayList<MyResponse>();
    try{
        //Run the process method and collect the result
        MyResponse response = process();
        List<MyCallable> next = callbacks.get(response.getResult());

        if (next != null && !next.isEmpty()){
            //Run within same thread, return results
            for (MyCallable m : next){
                resp.addAll(m.call();
            }
            return resp;
        } else {
            //No more responses, pass them back up the chain
            resp.add(response);
            return list;
        }
    //Anything goes wrong, we catch it here and wrap it in a response
    } catch (Exception e){
         resp.add(new MyExceptionResponse(e));
         return resp;
    }
}

//Implemented by all child classes, does the actual work  
public abstract MyResponse process() throws Exception;

これは、私がまだ実際にテストしていないプロトタイプでもあることに注意してください。したがって、これが完全ではないか、完全に実現可能であるとは限らないことを認識しています.

私が懸念しているのは、タスクがスレッド プールに追加され、実行が開始されることです。メイン スレッドでは、Future が作成され、それに対して .get(N, TimeUnit) が呼び出されて結果が取得されます。そのタスクがタイムアウトした場合はどうなりますか? TimeoutException が発生します。ここで、try/catch ブロック内で Future をキャンセルできますが、Future をキャンセルして結果を抽出する方法はありますか? 4 つ目のタスクが停止する前に、3 つのタスクが実行され、結果が返された可能性があります。MyCallable の try/catch は結果を返し、例外 (つまり、.cancel(true) が呼び出されたときに InterruptedException が呼び出された場合) が発生した場合はそれをチェーンにプッシュする必要がありますが、その結果を取得することは可能ですか?

もちろん、そもそも私がこれについて完全に間違っているとしたら、それも知っておくとよいでしょう。これは、マルチスレッドへの私の最初の大きな進出です。

編集: わかりました、それを念頭に置いて、 MyCallable クラスの周りにラッパーが配置されました。ラッパーは Callable を実装し、コレクションを返します。コレクションは MyCallable オブジェクトのチェーンに渡され、結果が追加されるため、Future.get がタイムアウトした場合、コレクションを取得して部分的な結果を取得できます。

ただし、これにより競合状態が発生する可能性があります。現在呼び出されている MyCallable が外部サービスを待機している場合、Future.cancel(true) 操作によって MyCallable 内で InterruptedException が発生します。これがキャッチされ、例外が応答オブジェクトにラップされ、コレクションに追加されます。問題は、メイン スレッドが Future をキャンセルし、ラッパーまたはラッパー内のコレクションを同期してからコレクションを取得すると、コレクションの取得と MyCallable の追加の try/catch ブロックとの間に競合状態が発生することです。コレクションへのラップされた例外? それとも、メイン スレッドは例外のキャッチを待ってから、次の行を実行しますか?

4

1 に答える 1

2

を取得した時点でTimeoutException、Executor Service にサブミットされたタスクは順調に進んでいます。例外を受け取ったのは待機しているだけです。これはおそらく、結果マップがまだ入力されていることを意味します。

あなたができることは、並行マップを使用して、タイムアウトが発生した後に存在する結果を安全に抽出することです。

于 2013-08-13T19:17:58.753 に答える