1

Future と Callable を使用して、dfs 再帰メソッドを並列に変換して効率を改善しようとしています。しかし、それを正しく行う方法がわかりません。コードは次のとおりです。

public MyResult compute(MyTree tree, int depth, ExecutorService exec) {
    if (depth >= 3) {
        Callable<MyResult> callable = new Callable<MyResult>() {
            @Override
            public MyResult call() throws Exception {
                return compute(tree, 0, exec);
            }
        };
        Future<MyResult> task = exec.submit(callable);
        return task.get();
    }
    else {
        MyResult result = new MyResult();
        if (something) {
            tree = tree.leftChild;
            result = compute(tree,depth+1,exec);
        }
        else if (something else){
            tree = tree.rightChild;
            result = compute(tree,depth+1,exec);
        }
        else
            return result;
    }
}

私が期待しているのは、再帰メソッドが task.get() の戻り値を待たずに計算を続けることです。したがって、深さ 3 に進むたびに、将来のタスクを送信し、別の子を計算するために戻りますが、タスクは同時に独自のサブツリーを計算します。

ただし、この方法はまだ並列ではなく、順番に行われていることがわかりました。(メソッドが呼び出されるたびに深さを出力しましたが、結果はフューチャーとエグゼキューターを使用しないメソッドと同じで、常に遅くなりました。)

これは Future と Callable を使用する正しい方法ではないと思います。いくつかの例を見つけましたが、再帰的な方法を使用していません。最も一般的な例は、Future List> のリストを持ち、毎回タスクを送信し、その後別のループで Future リストを反復することです。

Future と Executor を再帰的な方法で実装する方法を知っている人はいますか?

4

2 に答える 2

1

Java 1.7 ForkJoinPool の方が満足できるかもしれません。これは、特に再帰的な分割統治を目的としています。

于 2012-05-29T21:43:03.077 に答える
1
    Future<MyResult> task = exec.submit(callable);
    return task.get();

このコードは を呼び出すのと同じcallable.run()です。出力の Future.get() ブロック。

例が単純すぎるのかもしれません。ロジックが複数のサブツリーを処理する必要はないようです。同じノードから複数の再帰呼び出しが必要な場合は、Callable言及したように、それらすべてを s として送信し、それらすべてを別のループで待機できます。(もちろん、 ExecutorService にも複数のスレッドが必要です。)

于 2012-05-29T23:29:59.923 に答える