- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有 RecursiveAction
的下一个实现,这个类的唯一目的是从 0 打印到 9,但如果可能的话,从不同的线程打印:
public class MyRecursiveAction extends RecursiveAction {
private final int num;
public MyRecursiveAction(int num) {
this.num = num;
}
@Override
protected void compute() {
if (num < 10) {
System.out.println(num);
new MyRecursiveAction(num + 1).fork();
}
}
}
我认为调用 awaitQuiescence
将使当前线程等待,直到所有任务(提交和 fork )都将完成:
public class Main {
public static void main(String[] args) {
ForkJoinPool forkJoinPool = new ForkJoinPool();
forkJoinPool.execute(new MyRecursiveAction(0));
System.out.println(forkJoinPool.awaitQuiescence(5, TimeUnit.SECONDS) ? "tasks" : "time");
}
}
但我并不总是得到正确的结果,而不是打印 10 次,而是打印 0 到 10 次。
但如果我将 helpQuiesce
添加到 RecursiveAction
的实现中:
public class MyRecursiveAction extends RecursiveAction {
private final int num;
public MyRecursiveAction(int num) {
this.num = num;
}
@Override
protected void compute() {
if (num < 10) {
System.out.println(num);
new MyRecursiveAction(num + 1).fork();
}
RecursiveAction.helpQuiesce();//here
}
}
一切正常。
我想知道 awaitQuiescence
究竟在等待什么?
最佳答案
当您将 System.out.println(num);
更改为 System.out.println(num + ""+ Thread.currentThread() 时,您会知道会发生什么);
这可能会打印如下内容:
0 Thread[ForkJoinPool-1-worker-3,5,main]
1 Thread[main,5,main]
tasks
2 Thread[ForkJoinPool.commonPool-worker-3,5,main]
当 awaitQuiescence
检测到有待处理的任务时,它会通过窃取一个并直接执行它来提供帮助。 Its documentation说:
If called by a ForkJoinTask operating in this pool, equivalent in effect to ForkJoinTask.helpQuiesce(). Otherwise, waits and/or attempts to assist performing tasks until this pool isQuiescent() or the indicated timeout elapses.
我添加的重点
这发生在这里,正如我们所见,一个任务打印“main”作为它的执行线程。然后,fork()
的行为被指定为:
Arranges to asynchronously execute this task in the pool the current task is running in, if applicable, or using the
ForkJoinPool.commonPool()
if notinForkJoinPool()
.
由于main
线程不是ForkJoinPool
的工作线程,fork()
会将新任务提交给commonPool()
。从那时起,从公共(public)池的工作线程调用的 fork()
也将提交下一个任务到公共(public)池。但是在自定义池上调用的 awaitQuiescence
不会等待公共(public)池的任务完成,并且 JVM 过早终止。
如果你要说这是一个有缺陷的 API 设计,我不会反对。
解决方案是不要将 awaitQuiescence
用于除公共(public)池¹之外的任何内容。通常,拆分子任务的 RecursiveAction
应该等待它们完成。然后,您可以等待根任务完成,等待所有关联任务完成。
this answer的后半部分包含这样一个 RecursiveAction
实现的示例。
¹ awaitQuiescence
在您没有实际操作的情况下很有用,例如提交到公共(public)池的并行流。
关于java-8 - ForkJoinPool#awaitQuiescence 实际上是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66643737/
我有 RecursiveAction 的下一个实现,这个类的唯一目的是从 0 打印到 9,但如果可能的话,从不同的线程打印: public class MyRecursiveAction extend
我是一名优秀的程序员,十分优秀!