ForkJoinTask完成处理程序

时间:2013-09-02 03:21:21

标签: java promise future fork-join completionhandler

我有一个长期运行的计算,我已将其与Java's ForkJoinTask分开。

Java's FutureTask提供了一种模板方法done()Overriding this method allows for "registering a completion handler"

是否可以为ForkJoinTask注册完成处理程序?

我在问,因为我不想在我的应用程序中使用阻塞线程 - 但只要通过调用result = ForkJoinPool.invoke(myForkJoinTask)result = ForkJoinPool.submit(myForkJoinTask).get()检索计算结果,我的应用程序就会有阻塞线程

1 个答案:

答案 0 :(得分:1)

我认为你的意思是“锁定免费”编程http://en.wikipedia.org/wiki/Non-blocking_algorithm?虽然FutureTask.get()可能阻塞当前线程(因此留下一个空闲的CPU),但ForkJoinTask.get()(或join)会尝试使CPU保持忙碌状态。

如果你能够将你的问题分成许多小小的和平(ForkJoinTask),这种方法很有效。如果一个FJTask在内部等待另一个未准备好的任务的结果,那么ForkJoinTask会尝试从其ForkJoinPool中获取其他一些工作(Task),并同时执行该任务。

直到你的所有任务都受CPU限制,它才能正常工作:你的所有CPU都保持忙碌状态。 如果您的任何任务等待某些外部事件(即向火星探测器发送REST呼叫),它将不起作用。问题也应该形成DAG,否则你可能会陷入僵局。但是,在你加入之前在同一个任务中分叉的任务之前,它运行良好。如果你加入你最后分叉的任务,那就更好了。

因此,在任务中/之间调用get()或join()并不会太糟糕。

您提到了一个解决问题的完成处理程序。如果您自己实现ForkJoinTask,可以查看RecursiveTask甚至RecursiveAction。您将实现compute(),您可以轻松地将每个任务的结果转发到compute()函数末尾的某个收集器,而不是返回它。

但你必须考虑到你的收藏家会同时被召唤!要添加值或计算完成次数,请查看java.util.concurrent.atomic。避免使用同步块。否则,您的所有任务都必须等待这个单一瓶颈,并且只有一个CPU继续工作。

我认为传播结果涉及的问题多于返回它们(因为FJPool处理这个问题)。此外,很难决定(并与外界沟通)您的最终结果。