Проблема в том, что вы ждете, вызывая блокировку get
здесь:
for(Future<Integer> fut : list) {
System.out.println("From future is "+fut.get());
}
Чтобы решить эту проблему, вам нужно использовать реактивный код.Вы можете использовать завершаемый API будущего, который предназначен для декларативного реактивного API, подобного Future:
ExecutorService executor = Executors.newFixedThreadPool(10);
Supplier<Integer> call1Supplier = () -> {
System.out.println("Calling 1");
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
};
Supplier<Integer> call2Supplier = () -> {
System.out.println("Calling 1");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
};
Затем его можно отправить в ту же службу исполнителя, но с использованием реактивного CompletableFuture
, который поддерживаетобъекты, похожие на обратные вызовы.
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
CompletableFuture<Void> future =
CompletableFuture.supplyAsync(call1Supplier, executor)
.thenAccept(number -> System.out.println("From future is " + number));
futures.add(future);
} else {
CompletableFuture<Void> future =
CompletableFuture.supplyAsync(call2Supplier, executor)
.thenAccept(number -> System.out.println("From future is " + number));
futures.add(future);
}
}
Следующее просто для того, чтобы убедиться, что текущий поток не завершает работу до завершения всех асинхронных задач.Но если это долго работающее приложение, такое как сервер, это может быть ненужным
for (CompletableFuture<Void> future : futures) {
future.join();
}
Обратите внимание, что я выделил код из Call1
и Call2
, поскольку реализация Callable
не являетсянеобходимо.Но все же хорошая идея - хранить его в отдельном классе (если только объекты функций не в порядке).