在ForkJoinPool
ForkJoinTask
中,当前工作线程是否参与工作窃取?
我已经读到了fork连接池可以从阻塞或等待线程中窃取的含义。目前的工人似乎是一个明显的候选人一旦工作人员在另一个任务上调用.join()
,那么该任务基本上就被阻止了。
另一方面,我看到许多文章暗示不同的结论。例如,当前工作者线程在等待分叉任务之前应该工作的普遍共识。
有一些文章讨论了使用ForkJoinTask.getSurplusQueuedTaskCount
作为通过让当前工作人员完成一些工作来平衡队列中的工作的方法。如果当前工人也在偷窃,那么这似乎没有必要。
当然,我希望最大化线程操作并使所有工作人员最大限度地运行。了解当前线程是否也窃取了工作(例如,当调用.join
时)将有助于澄清。
答案 0 :(得分:2)
ForkJoinPool负责管理线程。客户端代码应该为其提供任务,而不是对线程进行微观管理。请注意,任务和线程是两回事;任务是要执行的工作单元,线程执行起作用。
如果任务足够大以便从并行运行部分任务中受益,那么forkJoinTask.compute()应该fork()到较小的子任务中;如果任务足够小以便最好在其中运行,则只需处理任务一个线程。如果工作结果超出预期,它可以fork()一些工作并完成剩下的工作。如果ForkJoinTask.compute()分叉成较小的子任务,它可以在返回之前调用join()。然后,ForkJoinPool将释放线程以处理其他任务,或者生成一个临时线程来处理其他任务,以确保充分利用可用的并行性。
我认为假设只要有未完成的任务,适当数量的工作线程保持忙,这是合理的,除非你在compute()方法中明确地阻塞线程。
Sun教程提供了有关如何使用这些类的更多细节:
https://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html