Метод whenComplete
Метод whenComplete класса CompletableFuture
позволяет выполнить некоторое действие после того,
как асинхронная задача завершится - независимо от того,
завершилась она успешно или с исключением.
В первый параметр мы передаем функцию BiFunction,
которая принимает результат выполнения задачи и исключение
(одно из них всегда будет null). Метод возвращает
новый объект CompletableFuture с тем же результатом
или исключением, что и исходный.
Важно понимать: если функция, переданная в whenComplete,
сама выбросит исключение, то результирующий
CompletableFuture завершится именно этим исключением.
Если же исходная задача завершилась с ошибкой, а функция
в whenComplete не выбросила исключение, то
результирующий объект сохранит исходное исключение.
Синтаксис
CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action)
CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action)
CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor)
Пример
Давайте создадим асинхронную задачу, которая успешно возвращает число, и выведем информацию о завершении:
import java.util.concurrent.CompletableFuture;
public class Main
{
public static void main(String[] args)
{
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
return 42;
});
CompletableFuture<Integer> res = future.whenComplete((value, ex) -> {
if (ex == null) {
System.out.println("Completed with value: " + value);
} else {
System.out.println("Completed with error: " + ex.getMessage());
}
});
System.out.println(res.join());
}
}
Результат выполнения кода:
"Completed with value: 42"
"42"
Пример
Теперь рассмотрим задачу, которая завершается с исключением:
import java.util.concurrent.CompletableFuture;
public class Main
{
public static void main(String[] args)
{
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("Something went wrong");
});
CompletableFuture<Integer> res = future.whenComplete((value, ex) -> {
if (ex == null) {
System.out.println("Completed with value: " + value);
} else {
System.out.println("Completed with error: " + ex.getMessage());
}
});
try {
res.join();
} catch (Exception e) {
System.out.println("Caught: " + e.getCause().getMessage());
}
}
}
Результат выполнения кода:
"Completed with error: Something went wrong"
"Caught: Something went wrong"
Пример
Давайте используем whenComplete для логирования
и посмотрим, что исходный результат сохраняется:
import java.util.concurrent.CompletableFuture;
public class Main
{
public static void main(String[] args)
{
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "abcde");
CompletableFuture<String> res = future.whenComplete((value, ex) -> {
System.out.println("Logging: task finished");
});
System.out.println(res.join());
}
}
Результат выполнения кода:
"Logging: task finished"
"abcde"
Смотрите также
-
класс
CompletableFuture,
который представляет асинхронную задачу -
метод
handle,
который позволяет преобразовать результат или исключение -
метод
exceptionally,
который обрабатывает исключение и возвращает значение по умолчанию -
метод
join,
который ожидает завершения задачи и возвращает результат