You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何异步调用两个Java Web服务以缩短总执行时间?

问题

我现有一段调用两个Web服务的代码,这两个服务均返回超大响应数据,单次请求分别耗时8秒和12秒。由于请求串行执行,总耗时达20秒。请问能否修改代码实现异步调用,使总耗时更接近12秒而非当前的20秒?

代码如下:

String listOfCities; 
String listOfCountries; 
try { 
    listOfCities = service.getListOfCities(host+"service/cities"); 
    listOfCountries = service.getListOfCountries(host+"service/countries"); 
} catch (Exception e) { 
    log.error("Failed to read service: " + e); 
}

感谢各位回复,我认为此问题并非重复提问,我需要等待两个线程均获取结果后再继续执行,下方解决方案可满足该需求。


解决方案

当然可以!通过异步并行调用这两个服务,完全能把总耗时压缩到接近较慢服务的12秒——毕竟两个请求可以同时发起,不用等第一个执行完再启动第二个,完美匹配你“等两个线程都获取结果再继续”的需求。

下面是基于Java 8+ CompletableFuture的实现方案,这是处理异步任务最常用的方式:

String listOfCities;
String listOfCountries;

try {
    // 同时启动两个异步请求,各自在独立线程中执行
    CompletableFuture<String> citiesFuture = CompletableFuture.supplyAsync(() -> 
        service.getListOfCities(host + "service/cities")
    );
    CompletableFuture<String> countriesFuture = CompletableFuture.supplyAsync(() -> 
        service.getListOfCountries(host + "service/countries")
    );

    // 阻塞等待两个异步任务全部完成,这一步耗时由最慢的请求决定(约12秒)
    CompletableFuture.allOf(citiesFuture, countriesFuture).join();

    // 安全获取两个任务的结果(此时任务已完成,不会额外阻塞)
    listOfCities = citiesFuture.get();
    listOfCountries = countriesFuture.get();
} catch (Exception e) {
    log.error("Failed to read services: " + e);
}

关键说明:

  • supplyAsync:将服务调用任务提交到默认的线程池执行,两个任务会同时启动,互不等待
  • CompletableFuture.allOf().join():专门用于等待多个异步任务全部完成,确保你不会在任意一个结果未就绪时就继续执行后续逻辑
  • 异常处理:如果任意一个服务调用抛出异常,join()或get()会抛出对应的异常,最终被外层的catch块捕获

进阶优化:自定义线程池

如果需要更可控的线程管理(比如避免默认线程池被其他任务占用),可以自定义线程池:

// 创建固定大小的线程池,这里因为只有两个任务,设置为2即可
ExecutorService customExecutor = Executors.newFixedThreadPool(2);

try {
    CompletableFuture<String> citiesFuture = CompletableFuture.supplyAsync(() -> 
        service.getListOfCities(host + "service/cities"), customExecutor
    );
    CompletableFuture<String> countriesFuture = CompletableFuture.supplyAsync(() -> 
        service.getListOfCountries(host + "service/countries"), customExecutor
    );

    CompletableFuture.allOf(citiesFuture, countriesFuture).join();

    listOfCities = citiesFuture.get();
    listOfCountries = countriesFuture.get();
} catch (Exception e) {
    log.error("Failed to read services: " + e);
} finally {
    // 关闭线程池(如果是全局复用的线程池,无需每次关闭)
    customExecutor.shutdown();
}

另外要注意:确保你的service实例是线程安全的,如果它不是线程安全的,建议在每个异步任务中创建独立的service实例,避免并发调用导致的问题。

内容的提问来源于stack exchange,提问作者user2254180

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:18:10