Future.get не может заблокировать поток в forkjoinpool / workstealingpool - PullRequest
3 голосов
/ 21 мая 2019

Я установил размер пула рабочих столов равным 1. Похоже, что future.get () не блокирует поток.

@Test
public void runAsyncThenApplyExample() {
    ExecutorService executor = Executors.newWorkStealingPool(1);
    CompletableFuture cf = CompletableFuture.supplyAsync(
            () -> {
                //assertTrue(Thread.currentThread().isDaemon());
                System.out.println("func: " + threadName());
                Callable<Long> callable = () ->stub();
                Future<Long> future = executor.submit(callable);
                try {
                    future.get();  <<<<< **I think this should block the thread**
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
                return 1;
            }, executor).thenAccept(s -> {
        System.out.println("accept: " + threadName());
    });
    //assertFalse(cf.isDone());
    System.out.println("main: " + threadName());
    sleep(10);
    assertTrue(cf.isDone());
}

private Long stub() {
    System.out.println("stub: " + threadName());
    return 1L;
}
private String threadName() {
    return Thread.currentThread().getName();
}

вывод:

func:ForkJoinPool-1-worker-3
main: main
заглушка: ForkJoinPool-1-worker-3
принимает: ForkJoinPool-1-worker-3

Кажется, что будущее.get () и заглушка используют одну и ту же тройку.enter image description here

enter image description here

Ответы [ 2 ]

2 голосов
/ 21 мая 2019

Executors.newWorkStealingPool(1); использует ForkJoinPool, у которого есть недокументированная функция, называемая компенсационными потоками.

От http://www.coopsoft.com/ar/CalamityArticle.html (акцент мой):

В JDK1.8 представлен класс CompletableFuture. Процитируем JavaDoc:

«Будущее, которое может быть явно завершено (с указанием его значения и статуса) и может включать в себя зависимые функции и действия, которые срабатывают после его завершения».

В JavaDoc не упоминается, что при использовании большого количества зависимых функций с методом get () платформа создает «потоки компенсации» для продолжения извлечения задач приложения из очереди запросов и отправки.

Поэтому, когда вы делаете future.get();, он блокируется, но создается другой поток, в котором выполняется задача.

Когда я запускаю ваш код, я получаю вывод:

func: ForkJoinPool-1-worker-1
главная: главная
заглушка: ForkJoinPool-1- worker-0
принять: ForkJoinPool-1-worker-1

Вы не показали свой метод threadName(), возможно, в нем есть ошибка, и из-за этого вы видите одно и то же имя потока (или вы используете другую JVM, которая в этом случае использует одно и то же имя, проверьте поток Я БЫ)? Если нет, предоставьте полный код, который выводит func и stub в виде одних и тех же потоков.

0 голосов
/ 21 мая 2019

Future.get () блоки, это означает, что код, следующий за Future.get (), не будет выполняться, пока не будет получен Результат.Даже в вашем выводе вы можете увидеть, что заглушка заканчивает выполнение первым.Можете ли вы попытаться заснуть 5 минут или около того в своем заглушке перед вашим ответом и посмотреть, что произойдет?

...