try (ForkJoinPool pool = new ForkJoinPool(2)) { // A new pool
ForkJoinTask adapt = ForkJoinTask.adapt(() -> {
Thread thread = Thread.currentThread();
assertTrue(thread instanceof ForkJoinWorkerThread);
// submit to common pool
List workers = range(0, 100).mapToObj(i -> CompletableFuture.supplyAsync(() -> {
LockSupport.parkNanos(1_000_000L);
return Thread.currentThread();
})).toList().stream()
.map(CompletableFuture::join) // join in current ForkJoinWorkerThread
.toList();
if (Runtime.version().feature() < 25) {
// before 25, ForkJoinWorkerThread won't help for a different ForkJoinPool
assertThat(workers).doesNotContain(thread);
} else {
// after 25, the ForkJoinWorkerThread will help even from a different ForkJoinPool
assertThat(workers).contains(thread);
}
});
pool.execute(adapt);
adapt.join();
}
Я не уверен, что это специально. Разница заключается в ForkJoinPool#helpAsyncBlocker(Executor, ForkJoinPool.ManagedBlocker).
Я обнаружил, что поведение CompletableFuture и ForkJoinPool отличается от Java 25. Вот тест: [code]try (ForkJoinPool pool = new ForkJoinPool(2)) { // A new pool ForkJoinTask adapt = ForkJoinTask.adapt(() -> { Thread thread = Thread.currentThread(); assertTrue(thread instanceof ForkJoinWorkerThread); // submit to common pool List workers = range(0, 100).mapToObj(i -> CompletableFuture.supplyAsync(() -> { LockSupport.parkNanos(1_000_000L); return Thread.currentThread(); })).toList().stream() .map(CompletableFuture::join) // join in current ForkJoinWorkerThread .toList(); if (Runtime.version().feature() < 25) { // before 25, ForkJoinWorkerThread won't help for a different ForkJoinPool assertThat(workers).doesNotContain(thread); } else { // after 25, the ForkJoinWorkerThread will help even from a different ForkJoinPool assertThat(workers).contains(thread); } }); pool.execute(adapt); adapt.join(); } [/code] Я не уверен, что это специально. Разница заключается в ForkJoinPool#helpAsyncBlocker(Executor, ForkJoinPool.ManagedBlocker).