我正在尝试使用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和executor的方法相同,而且总是更慢。)
我相信这不是使用Future和Callable的正确方法,我找到了一些例子,但他们没有使用递归方法。最常见的例子是有一个Future List&gt;列表,每次都提交一个任务,然后在另一个循环中迭代Future列表。
有谁知道如何在递归方法中实现Future和Executor?
答案 0 :(得分:1)
Future<MyResult> task = exec.submit(callable);
return task.get();
此代码等同于调用callable.run()
。 Future.get()阻塞输出。
也许这个例子太简单了。似乎逻辑永远不需要处理多个子树。如果您需要来自同一节点的多个递归调用,您可以将它们全部作为Callable
提交,并在单独的循环中等待它们,如您所述。 (当然,您的ExecutorService也需要有多个线程。)
答案 1 :(得分:0)
你可能会对Java 1.7 ForkJoinPool感到满意,它专门针对递归的分而治之。