在Java 7+ ForkJoinPool中,是否可以取消任务和所有子任务?

Dav*_*aux 8 java java.util.concurrent fork-join

我的程序通过分而治之的方法搜索问题的解决方案(任何解决方案),使用递归和实现RecursiveTasks:我为该部门的第一个分支派一个任务,然后递归到第二个分支:如果第二个分支找到了解决方案,然后我取消了第一个分支,否则我等待它的结果.

这可能不是最佳的.如果找到解决方案,一种方法是针对任何已启动的任务抛出异常.但是,我将如何取消所有已启动的任务?取消任务是否也取消所有子任务?

edh*_*ned 1

框架无法取消任务的原因与无法取消线程的原因相同。有关所有原因,请参阅有关 Thread.stop() 的文档。该任务可能持有什么锁?它可以链接到哪些外部资源?所有相同的 Thread.stop() 原因也适用于任务(毕竟,任务在线程下运行)。您需要告诉任务停止,就像告诉线程停止一样。

\n\n

我管理另一个使用分散-聚集技术的 fork/join 项目。我执行取消或短路的方式是,我创建的每个任务都会传递一个对象 (PassObject),该对象具有

\n\n
protected volatile boolean stop_now = false;\n
Run Code Online (Sandbox Code Playgroud)\n\n

以及停止任务的方法

\n\n
protected void stopNow() {stop_now = true; }\n
Run Code Online (Sandbox Code Playgroud)\n\n

每个任务都会定期检查 stop_now,当 true 时,它​​会正常结束任务。

\n\n

不幸的是,stop_now 需要是易失性的,因为另一个线程将要设置它。如果您经常检查,这可能会增加大量开销。

\n\n

如何在另一个任务中设置这个字段有点棘手。我创建的每个任务还​​包含对每个其他任务的引用数组的引用

\n\n
int nbr_tasks = nbr_elements / threshold;\n// this holds the common class passed to each task\nPassObject[] passList = new PassObject[nbr_tasks];\n for (int i = 0; i < nbr_tasks; i++) \npassList[i] = new PassObject( passList,\xe2\x80\xa6 other parms);\n
Run Code Online (Sandbox Code Playgroud)\n\n

一旦列表形成,我就 fork() passList 中的每个对象。每个 PassObject 都包含对数组 passList 的引用,该数组包含对传递给每个任务的每个对象的引用。因此,每个任务都知道其他每个任务,并且当一个任务想要取消其他任务时,它只需调用 cancelOthers 方法并引用 passList 即可。

\n\n
private void cancelOthers (PassObject[] others) {\n// tell all tasks to stop\n for (int i = 0, max = others.length; i < max; i++)\nothers[i].stopNow();\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果您\xe2\x80\x99 使用 Java8,那么您可以使用 CountedCompler 类而不是 RecusiveTask 进行某种形式的分散-聚集。对于 Java7 或者如果您仍然想使用 RecursiveTask,则递归中的第一个任务需要创建一个 AtomicBoolean 字段 (AtomicBoolean stop_now = new AtomicBoolean(false);) 并在它创建的每个新 RecursiveTask 中包含对此字段的引用。通过递归,您\xe2\x80\x99不知道一开始需要多少层任务。\n同样,您\xe2\x80\x99需要定期检查代码中布尔值是否为真,当为真时,优雅地结束任务。

\n\n

以上只是有关如何取消的提示。每个应用程序都是不同的。我所做的适用于我的应用程序 \xe2\x80\x93 但逻辑是相同的。您需要在每个任务中都有一些通用的东西,一个任务可以设置并且每个其他任务都可以看到。

\n\n

我想添加更多代码,但代码插入一次只占用一行,这是不切实际的。

\n