В моем коде я создаю 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
*/