Java 不等待异步调用响应

Posted

技术标签:

【中文标题】Java 不等待异步调用响应【英文标题】:Java doesn't wait for asynchronous call response 【发布时间】:2021-11-24 14:54:45 【问题描述】:

我在 Java 中使用ExecutorService 创建一个线程池,其中每个线程执行一些异步任务/调用另一个服务。我不想等待响应,而是在响应到达时返回。

ExecutorService executor = Executors.newFixedThreadPool(5);  // Class var

// Method
Future<Object> future = executor.submit(new TransportService(requestVO));
Object response = future.get(5, TimeUnit.SECONDS);  // blocking  

这样做会等待第一个请求完成,然后返回结果。问题是第二个请求必须等待第一个请求的响应返回,并且仅在此之后处理。如果我使用 CompletableFuture 的 supplyAsync() 方法也会发生同样的事情,因为我还必须使用 join() 来获取响应。

我希望所有请求都通过并在响应到达时返回。这是可以实现的吗?流程仍然需要同步。

【问题讨论】:

第二个请求在哪里?您是否在循环中运行给定的代码? @StephanStahlmann 我正在循环调用该方法。 您的标题与您的问题相反。您希望 Java 不等待,但您(尚未)找到可以让您这样做的 API。 【参考方案1】:

您或许可以使用CompletableFuture 将异步任务提供给ExecutorService

    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "foo", Executors.newSingleThreadExecutor());
    future.thenAccept(s -> System.out.println("done: " + s));

CompletableFuture 有多个 then... 方法用于在完成时链接后续操作。

【讨论】:

【参考方案2】:

您需要在集合中添加期货,然后在最后调用 join/get。

Collection<Future<Object>> futures = new ArrayList<>();
// schedule calls independantly
for(Request vo: requests) 
   futures.add(executor.submit(new TransportService(requestVO)));

// actually handle result
for(Future<Object> future: futures) 
   Object response = future.get(5, TimeUnit.SECONDS);

在这种情况下,您最多可以安排五个作业。

【讨论】:

以上是关于Java 不等待异步调用响应的主要内容,如果未能解决你的问题,请参考以下文章

如何让我的异步客户端调用套接字服务器并等待响应

java中5种异步转同步方法

Java异步调用转同步的5种方式

同步异步阻塞非阻塞 总结

如何让 Lambda 函数等待异步操作完成?

进价程序员:5种必会的Java异步调用转同步的方法你会几种?