在我的代码中,我创建一个ForkJoinTask,并在此任务的运行库中派生一个新任务,并调用newTask.get(7,TimeUnit)。新任务休眠10秒钟。当原始任务提交到公共池时,我得到一个TimeoutException。但是,当使用自定义的ForkJoinPool时,则newTask.get(7,TimeUnit)等待任务完成。同样,在commonPool情况下,即使我取消了newTask,它仍然可以运行到完成状态,并且不会以InterruptedException结尾。这是在Java 8上。
问题是:为什么forkJoinTask.get(7,TimeUnit)在某些情况下会忽略超时,为什么forkJoinTask.cancel(true)不会引发InterruptedException?
public class ForkJoinQuestion {
private static final long START = System.currentTimeMillis();
private static final boolean COMMON_FORK_JOIN_POOL = false;
private final ForkJoinPool service = COMMON_FORK_JOIN_POOL ? ForkJoinPool.commonPool() : new ForkJoinPool(1);
public static void main(String[] args) throws InterruptedException {
ForkJoinQuestion question = new ForkJoinQuestion();
question.first();
Thread.sleep(17000);
System.out.println(time() + "Finished main");
}
private void first() {
service.submit(() -> {
System.out.println(time() + "Entered first");
ForkJoinTask<?> next = second();
next.fork();
try {
next.get(7000, TimeUnit.MILLISECONDS);
sleep(1); // do some computations
System.out.println(time() + "finished first");
} catch (Exception e) {
next.cancel(true);
System.out.println(time() + "[Exception in first] " + e.toString());
throw new RuntimeException(e);
}
});
}
private ForkJoinTask<?> second() {
return ForkJoinTask.adapt(() -> {
System.out.println(time() + "Entered second");
sleep(10);
System.out.println(time() + "finished second");
});
}
private static void sleep(int numSeconds) {
try {
System.out.println(time() + "Waiting " + numSeconds + " seconds");
Thread.sleep(numSeconds * 1000);
} catch (InterruptedException e) {
System.out.println(time() + "caught interrupted exception during sleep(" + numSeconds + ")");
}
}
private static String time() {
long time = System.currentTimeMillis() - START;
return Long.toString(time) + " : " + Thread.currentThread().getName() + " : ";
}
/*
When using the common pool the output is like this:
48 : ForkJoinPool.commonPool-worker-1 : Entered first
51 : ForkJoinPool.commonPool-worker-2 : Entered second
51 : ForkJoinPool.commonPool-worker-2 : Waiting 10 seconds
7053 : ForkJoinPool.commonPool-worker-1 : [Exception in first] java.util.concurrent.TimeoutException
10055 : ForkJoinPool.commonPool-worker-2 : finished second
17048 : main : Finished main
Looks mostly good, but I was expecting that second would be cancelled so "finished second" should not be in the output.
But when using a custom fork join pool, the timeout is not honored:
47 : ForkJoinPool-1-worker-1 : Entered first
50 : ForkJoinPool-1-worker-1 : Entered second
50 : ForkJoinPool-1-worker-1 : Waiting 10 seconds
10050 : ForkJoinPool-1-worker-1 : finished second
10050 : ForkJoinPool-1-worker-1 : Waiting 1 seconds
11050 : ForkJoinPool-1-worker-1 : finished first
17050 : main : Finished main
*/