← Назад к вопросам
В чем разница между Future и CompletableFuture?
2.3 Middle🔥 121 комментариев
#Многопоточность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между Future и CompletableFuture
Future (Java 5+)
Future — это интерфейс для представления результата асинхронного вычисления.
ExecutorService executor = Executors.newFixedThreadPool(2);
// Отправляем задачу в фон
Future<String> future = executor.submit(() -> {
Thread.sleep(1000);
return "Result";
});
// Ждём результат (блокирующий вызов)
String result = future.get(); // блокирует текущий поток
System.out.println(result); // "Result"
// Проверяем статус
if (future.isDone()) {
System.out.println("Готово");
}
// Отмена
future.cancel(true); // попытка отменить задачу
Основные методы Future:
get()— получить результат (блокирует)get(timeout, unit)— получить с таймаутомisDone()— проверить завершениеisCancelled()— проверить отменуcancel(mayInterrupt)— отменить задачу
Проблемы Future
Проблема 1: Блокирующий вызов
// Ждём результат — текущий поток заморожен
String result1 = future1.get(); // блокирует
String result2 = future2.get(); // блокирует
System.out.println(result1 + result2);
Это неэффективно в асинхронных системах. Поток впустую ждёт вместо выполнения других задач.
Проблема 2: Нельзя объединить несколько Future
// Хотим выполнить две задачи последовательно
Future<Integer> future1 = executor.submit(() -> 10);
Future<Integer> future2 = executor.submit(() -> 20);
// Как сложить? Нужно блокировать
int sum = future1.get() + future2.get(); // два блока
Проблема 3: Нельзя применить трансформацию
// Нет встроенного способа преобразовать результат
Future<String> future = executor.submit(() -> "5");
Future<Integer> intFuture = ??? // как конвертировать в int?
CompletableFuture (Java 8+)
CompletableFuture решает все проблемы Future. Это полнофункциональная реализация, которая позволяет:
// 1. Явно завершить результат (не нужно executor)
CompletableFuture<String> future = new CompletableFuture<>();
future.complete("Success");
String result = future.get(); // "Success"
// 2. Цепочка обработки (не блокирует)
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> f2 = f1.thenApply(x -> x * 2); // 20
CompletableFuture<String> f3 = f2.thenApply(String::valueOf); // "20"
// 3. Комбинирование Future
CompletableFuture<Integer> a = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> b = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Integer> combined = a.thenCombine(b, Integer::sum);
combined.whenComplete((result, exception) -> {
if (exception == null) {
System.out.println(result); // 30
}
});
Ключевые методы CompletableFuture
Создание:
// Сразу с результатом
CompletableFuture<String> f1 = CompletableFuture.completedFuture("value");
// Асинхронно (в ForkJoinPool)
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> "result");
// Асинхронно в своём executor
ExecutorService executor = Executors.newFixedThreadPool(2);
CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> "result", executor);
// Пустой future для явного завершения
CompletableFuture<String> f4 = new CompletableFuture<>();
f4.complete("done");
Трансформация результата:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 5);
// thenApply: синхронная трансформация
future.thenApply(x -> x * 2) // 10
.thenApply(String::valueOf) // "10"
.thenAccept(System.out::println);
// thenApplyAsync: асинхронная трансформация в отдельном потоке
future.thenApplyAsync(x -> {
Thread.sleep(1000);
return x * 3;
});
Комбинирование нескольких Future:
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> 20);
// thenCombine: оба результата
CompletableFuture<Integer> sum = f1.thenCombine(f2, Integer::sum); // 30
// thenAcceptBoth: обработать оба, ничего не вернуть
f1.thenAcceptBoth(f2, (a, b) -> System.out.println(a + b));
// allOf: дождаться всех
CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2);
all.whenComplete((v, ex) -> System.out.println("All done"));
// anyOf: первый завершившийся
CompletableFuture<Object> any = CompletableFuture.anyOf(f1, f2);
any.whenComplete((result, ex) -> System.out.println(result));
Обработка ошибок:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
if (Math.random() > 0.5) {
throw new RuntimeException("Error!");
}
return 42;
});
// exceptionally: восстановление
future.exceptionally(ex -> {
System.out.println("Ошибка: " + ex.getMessage());
return 0; // значение по умолчанию
});
// whenComplete: обработка в обоих случаях
future.whenComplete((result, exception) -> {
if (exception != null) {
System.out.println("Ошибка: " + exception);
} else {
System.out.println("Успех: " + result);
}
});
// handle: трансформация с обработкой ошибок
future.handle((result, exception) -> {
if (exception != null) return 0;
return result * 2;
});
Практический пример: цепочка операций
// Без CompletableFuture (блокирующий, неудобный код)
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> f1 = executor.submit(() -> fetchUser("john"));
String user = f1.get(); // блокирует
Future<Integer> f2 = executor.submit(() -> getScore(user));
Integer score = f2.get(); // блокирует
Future<String> f3 = executor.submit(() -> formatResult(score));
String result = f3.get(); // блокирует
// С CompletableFuture (неблокирующий, красивый код)
CompletableFuture.supplyAsync(this::fetchUser)
.thenApplyAsync(this::getScore)
.thenApplyAsync(this::formatResult)
.thenAccept(System.out::println)
.exceptionally(ex -> {
System.err.println("Pipeline failed: " + ex.getMessage());
return null;
});
Сравнение Future vs CompletableFuture
| Характеристика | Future | CompletableFuture |
|---|---|---|
| Блокирующий get() | Да | Да (но не нужен) |
| Трансформация | Нет | Да (thenApply) |
| Объединение | Нет | Да (thenCombine) |
| Обработка ошибок | Нет | Да (exceptionally) |
| Явное завершение | Нет | Да (complete) |
| Неблокирующие callbacks | Нет | Да (whenComplete) |
| Асинхронные операции | Нет | Да (Async методы) |
| Сложность | Простой | Полнофункциональный |
Выводы
- Future — базовый интерфейс, требует блокирующего get()
- CompletableFuture — современный инструмент для асинхронного программирования
- Используйте CompletableFuture для:
- Цепочек асинхронных операций
- Комбинирования результатов
- Обработки ошибок
- Неблокирующего кода
- Future ещё используется в legacy коде и как возвращаемый тип в некоторых библиотеках