CompletableFuture не работает должным образом - PullRequest
0 голосов
/ 14 декабря 2018

Я пытаюсь понять работу CompletableFuture из Java 8. Ниже код работает, как ожидалось

CompletableFuture.supplyAsync(() -> {
    System.out.println("supplyAsync Thread name " + Thread.currentThread().getName());
    return "str";
}).thenApply(str -> {
    System.out.println("thenApply Thread name " + Thread.currentThread().getName());
    return str;
}).thenApply(str1 -> {
    System.out.println("thenApply Thread name " + Thread.currentThread().getName());
    return str1;
}).thenAccept(str3 -> {
    System.out.println("thenAccept Thread name " + Thread.currentThread().getName());
});
System.out.println("Thread name " + Thread.currentThread().getName());

Вывод:

supplyAsync Thread name ForkJoinPool.commonPool-worker-1
thenApply Thread name main
thenApply Thread name main
thenAccept Thread name main
Thread name main

Но когда я вставил некоторые вычисления, это не работает должным образом, пожалуйста, исправьте меня, если я что-то упустил.

CompletableFuture.supplyAsync(() -> {
    System.out.println("supplyAsync Thread name " + Thread.currentThread().getName());
    long val = 0;
    for (long i = 0; i < 1000000; i++) {
        val++;
    }
    return "str";
}).thenApply(str -> {
    System.out.println("thenApply Thread name " + Thread.currentThread().getName());
    long val = 0;
    for (long i = 0; i < 1000000; i++) {
        val++;
    }
    return str;
}).thenApply(str1 -> {
    System.out.println("thenApply Thread name " + Thread.currentThread().getName());
    long val = 0;
    for (long i = 0; i < 1000000; i++) {
        val++;
    }
    return str1;
}).thenAccept(str3 -> {
    System.out.println("thenAccept Thread name " + Thread.currentThread().getName());
    long val = 0;
    for (long i = 0; i < 1000000; i++) {
        val++;
    }
});

System.out.println("Thread name " + Thread.currentThread().getName());

Вывод:

supplyAsync Thread name ForkJoinPool.commonPool-worker-1
Thread name main

Я согласен, что я не присоединяю дочерний поток к основномунить.Насколько я понимаю, дочерний поток должен печатать операторы независимо от основного потока.Вопрос в том, почему он вообще не печатает.

1 Ответ

0 голосов
/ 14 декабря 2018

Пояснение

Вы не присоединяете дочерний поток ForkJoinPool.commonPool-worker-1 к основному потоку.Таким образом, он уничтожается, как только поток main завершается.

Решение

Попробуйте вызвать .join() для вашего полного будущего в какой-то момент в вашем коде.Обратите внимание, что этот метод блокирует поток main.Таким образом, выполнение после точки соединения будет приостановлено до тех пор, пока дочерний поток не завершит выполнение.

CompletableFuture.supplyAsync(() -> {
    System.out.println("=> supplyAsync Thread name " + Thread.currentThread().getName());
    // ...
}).thenApply(str -> {
    System.out.println("thenApply Thread name " + Thread.currentThread().getName());
    // ...
}).thenApply(str1 -> {
    System.out.println("thenApply Thread name " + Thread.currentThread().getName());
    // ...
}).thenAccept(str3 -> {
    System.out.println("thenAccept Thread name " + Thread.currentThread().getName());
    // ...
}).join()

Напечатает:

supplyAsync Thread name ForkJoinPool.commonPool-worker-1
thenApply Thread name ForkJoinPool.commonPool-worker-1
thenApply Thread name ForkJoinPool.commonPool-worker-1
thenAccept Thread name ForkJoinPool.commonPool-worker-1
Thread name main

Если вы хотите, чтобы последний System.out.println(...) не зависел отвыполнение дочернего потока, затем присвойте вашу CompletableFuture переменной и присоедините ее в самом конце main:

CompletableFuture<Void> future = CompletableFuture.supplyAsync(...) ... // 

System.out.println("Thread name " + Thread.currentThread().getName());

future.join();    
...