Java Fork join:Fork所有子任务或为当前线程保留一个子任务
我试图了解fork-join如何工作的细节 Wikipedia有下面的合并排序示例,其中左半部分是分叉的,右半部分由当前线程处理Java Fork join:Fork所有子任务或为当前线程保留一个子任务,java,fork-join,Java,Fork Join,我试图了解fork-join如何工作的细节 Wikipedia有下面的合并排序示例,其中左半部分是分叉的,右半部分由当前线程处理 mergesort(A, lo, hi): if lo < hi: // at least one element of input mid = ⌊(hi - lo) / 2⌋ fork mergesort(A, lo, mid) // process (potentially)
mergesort(A, lo, hi):
if lo < hi: // at least one element of input
mid = ⌊(hi - lo) / 2⌋
fork mergesort(A, lo, mid) // process (potentially) in parallel with main task
mergesort(A, mid, hi) // main task handles second recursion
join
merge(A, lo, mid, hi)
mergesort(A、lo、hi):
如果lo
但是,我所看到的大多数Java示例都是fork所有子任务并等待结果:
for (Document document : folder.getDocuments()) {
DocumentSearchTask task = new DocumentSearchTask(document, searchedWord);
forks.add(task);
task.fork();
}
for (RecursiveTask<Long> task : forks) {
count = count + task.join();
}
return count;
(文档:folder.getDocuments())的{
DocumentSearchTask任务=新建DocumentSearchTask(文档,searchedWord);
forks.add(任务);
task.fork();
}
for(递归任务:forks){
count=count+task.join();
}
返回计数;
Wikipedia的例子对我来说更有意义,因为线程将做一些有用的事情,而不是阻塞和等待子任务
另一方面,如果我们分叉所有任务,就会避免递归,并且无法获得stackoverflowerrror
拆分任务的首选方法是什么?为什么?我认为首选方法是以相同的方式分叉和处理所有子任务。以下是一些原因:
ForkJoinPool
实现了ExecutorService
。请注意,ExecutorService
中的所有方法都是异步的。这是有原因的-您通常可以在后台异步生成一些计算,而您的主线程可以在需要计算结果之前完成一些其他有用的工作,例如生成更多异步任务更新:关于太多线程阻塞,这与
ForkJoinPool
无关。如前所述,ForkJoinPool
的特殊之处在于工作窃取确实发生在join
调用中 那么你的问题是什么呢?我担心会有大量线程被阻止等待。但是Doug Lea关于fork-join的论文说,“当工作线程遇到连接操作时,它会处理其他任务(如果可用),直到发现目标任务已经完成(通过isDone)”。所以,我想把所有的子任务分开是一种更好的一致性方法。是的,我已经用一个可能感兴趣的链接更新了我的答案。我还隐式假设两个版本中的join
都是ForkJoinPool连接。其他同步实际上是阻塞的,只有ForkJoinPool是特殊的。