我认为您的意思是“无锁”编程http://en.wikipedia.org/wiki/Non-blocking_algorithm?虽然 FutureTask.get() 可能会阻塞当前线程(从而留下空闲的 CPU),但 ForkJoinTask.get()(或连接)试图保持 CPU 忙碌。
如果您能够将问题拆分为许多小问题(ForkJoinTask),则此方法效果很好。如果一个 FJTask 在内部等待另一个尚未准备好的任务的结果,则 ForkJoinTask 会尝试从其 ForkJoinPool 中提取一些其他工作(任务)并同时执行该任务。
直到您的所有任务都受 CPU 限制,它才能正常工作:您所有的 CPU 都保持忙碌。如果您的任何任务等待某些外部事件(即向火星探测器发送 REST 调用),则它不起作用。问题也应该形成DAG,否则您可能会陷入僵局。但是,除非您只在同一个任务中加入之前分叉的任务,否则它运行良好。如果你最后加入你分叉的任务,那就更好了。
因此,在您的任务之内/之间调用 get() 或 join() 并不会太糟糕。
您提到了一个完成处理程序来解决问题。如果你自己实现 ForkJoinTask,你可以看看 RecursiveTask 甚至 RecursiveAction。您将实现 compute(),并且您可以轻松地将每个任务的结果转发到 compute() 函数末尾的某个收集器,而不是返回它。
但是你必须考虑到你的收集器会被同时调用!要添加值或计算完成计数,请查看java.util.concurrent.atomic。避免使用同步块。否则,您的所有任务都必须等待这个单一的瓶颈,并且只有一个 CPU 继续工作。
我认为传播结果比返回结果涉及更多问题(因为 FJPool 处理了这个问题)。此外,在什么时候完成最终结果变得难以决定(并与外界沟通)。