我尝试使用ForkJoinPool来并行计算我的CPU密集型任务。我理解ForkJoinPool会继续工作直到没有任务可执行。不幸的是,我经常观察到工作线程处于空闲/等待状态,因此并没有充分利用所有CPU。有时我甚至观察到额外的工作线程。
我没有预料到这一点,因为我严格尝试使用非阻塞式任务。我的观察结果与ForkJoinPool似乎浪费了一个线程非常相似。在对ForkJoinPool进行了大量调试后,我有一个猜想:
我使用invokeAll()将任务分配给子任务列表。在invokeAll()完成执行第一个任务后,它开始加入其他任务。这很好,直到要加入的下一个任务在执行队列的顶部。不幸的是,我异步提交了其他任务而没有加入它们。我希望ForkJoin框架能够继续先执行这些任务,然后再返回加入任何剩余的任务。
但是似乎这种方式不起作用。相反,工作线程会调用wait()而被阻塞,直到等待的任务准备就绪(可能是由另一个工作线程执行)。我没有验证过,但这似乎是调用join()的一个普遍缺陷。
ForkJoinPool提供了asyncMode,但这是一个全局参数,不能用于个别提交。但我希望看到我的异步forked任务能够很快执行。
那么,为什么ForkJoinTask.doJoin()不只是在其队列顶部执行任何可用任务,直到它准备就绪(由自己执行或被其他人窃取)呢?
我没有预料到这一点,因为我严格尝试使用非阻塞式任务。我的观察结果与ForkJoinPool似乎浪费了一个线程非常相似。在对ForkJoinPool进行了大量调试后,我有一个猜想:
我使用invokeAll()将任务分配给子任务列表。在invokeAll()完成执行第一个任务后,它开始加入其他任务。这很好,直到要加入的下一个任务在执行队列的顶部。不幸的是,我异步提交了其他任务而没有加入它们。我希望ForkJoin框架能够继续先执行这些任务,然后再返回加入任何剩余的任务。
但是似乎这种方式不起作用。相反,工作线程会调用wait()而被阻塞,直到等待的任务准备就绪(可能是由另一个工作线程执行)。我没有验证过,但这似乎是调用join()的一个普遍缺陷。
ForkJoinPool提供了asyncMode,但这是一个全局参数,不能用于个别提交。但我希望看到我的异步forked任务能够很快执行。
那么,为什么ForkJoinTask.doJoin()不只是在其队列顶部执行任何可用任务,直到它准备就绪(由自己执行或被其他人窃取)呢?