Ответ
CompletableFuture<T> — это класс, появившийся в Java 8, который представляет собой отложенный результат асинхронной операции. Он сочетает в себе возможности Future (представление будущего результата) и CompletionStage (возможность строить цепочки и комбинировать асинхронные задачи).
Ключевые возможности:
- Явное завершение: Вы можете завершить
CompletableFutureвручную с результатом (complete(T value)) или исключением (completeExceptionally(Throwable ex)). - Цепочки вызовов (chaining): Позволяет описывать поток обработки: "когда завершится эта задача, сделай то, затем другое".
- Комбинация нескольких Future: Объединение результатов двух и более независимых асинхронных задач.
- Гибкая обработка исключений прямо в цепочке.
- Асинхронное выполнение с использованием пулов потоков (
ForkJoinPool.commonPool()по умолчанию или своего).
Основные методы для построения цепочек:
thenApply(Function)— преобразует результат (синхронно).thenApplyAsync(Function)— преобразует результат асинхронно.thenAccept(Consumer)— потребляет результат без возврата значения.thenCompose(Function)— "плоское" преобразование (композиция Future).thenCombine(CompletionStage, BiFunction)— объединяет результаты двух Future.exceptionally(Function)— обрабатывает исключение, возвращая резервное значение.handle(BiFunction)— обрабатывает и результат, и исключение.
Практический пример: параллельный вызов двух сервисов и объединение результата.
import java.util.concurrent.CompletableFuture;
public class OrderService {
// Имитация асинхронных вызовов
CompletableFuture<Double> getPriceAsync(String productId) {
return CompletableFuture.supplyAsync(() -> {
// Долгий вызов к Price Service
return 99.99;
});
}
CompletableFuture<Double> getDiscountAsync(String userId) {
return CompletableFuture.supplyAsync(() -> {
// Долгий вызов к Discount Service
return 0.1; // 10% скидка
});
}
public CompletableFuture<Double> calculateTotalAsync(String productId, String userId) {
CompletableFuture<Double> priceFuture = getPriceAsync(productId);
CompletableFuture<Double> discountFuture = getDiscountAsync(userId);
// Комбинируем результаты, когда оба Future завершатся
return priceFuture.thenCombine(discountFuture, (price, discountRate) -> {
return price * (1 - discountRate); // Итоговая цена со скидкой
}).exceptionally(ex -> { // Обработка ошибок в любой из задач
System.err.println("Ошибка расчета: " + ex.getMessage());
return 0.0; // Возвращаем значение по умолчанию
});
}
public static void main(String[] args) throws Exception {
OrderService service = new OrderService();
CompletableFuture<Double> totalFuture = service.calculateTotalAsync("prod1", "user42");
// Блокирующее ожидание результата (в реальном коде лучше использовать thenAccept)
Double total = totalFuture.get();
System.out.println("Итоговая цена: " + total); // Выведет: Итоговая цена: 89.991
}
}
Использование: CompletableFuture — основной инструмент для неблокирующего асинхронного программирования в современных Java-приложениях, особенно в микросервисных архитектурах и высоконагруженных веб-сервисах.