Когда вы говорите, что хотите знать, можно ли «выполнить завершаемое будущее в потоке, в котором оно было создано», вы демонстрируете неправильное мышление. A CompletableFuture
не работает. CompletableFuture
просто инкапсулирует значение или исключение, которое может быть установлено не более одного раза, которое мы называем завершением it.
API предлагает множество методов для планирования попыток завершения, потенциально асинхронный, но не стоит отвлекаться от того, что вы решаете, как его завершить.
Существуют простые альтернативы асинхронному завершению:
CompletableFuture<String> f = CompletableFuture.completedFuture("hello");
создает немедленно завершенное будущее. Java 9 добавляет failedFuture
для поддержки создания сразу же исключительно завершенного будущего.
Вы также можете легко создать будущее, которое будет завершено позднее в том же потоке:
CompletableFuture<String> f = new CompletableFuture<>();
// arbitrary actions
f.complete("hello");
Вы также можно использовать фабричные методы с исполнителем, немедленно запустив действие в инициирующем потоке:
CompletableFuture<String> f
= CompletableFuture.supplyAsync(() -> "hello", Runnable::run);
или
CompletableFuture<String> f
= CompletableFuture.supplyAsync(() -> {
if(Math.random() > 0.5) throw new IllegalStateException();
return "hello";
}, Runnable::run);
, чтобы продемонстрировать разницу с вызовом complete
или создание немедленно завершенного будущего.
Конечно, эти возможности могут быть объединены с другими функциями, такими как allOf
:
CompletableFuture<String> a = new CompletableFuture<>();
CompletableFuture<String> b = new CompletableFuture<>();
CompletableFuture<String> c = new CompletableFuture<>();
CompletableFuture.allOf(a, b, c).whenComplete((__, t) -> {
if(t != null) System.err.println("failed with "+t);
else System.out.println("all completed "+a.join()+", "+b.join()+", "+c.join());
});
System.out.println("step 1");
a.complete("foo");
System.out.println("step 2");
b.complete("bar");
System.out.println("step 3");
c.complete("baz");