异步调用两个Java方法

时间:2018-01-24 15:36:35

标签: java multithreading asynchronous

我有以下代码调用两个Web服务。两个Web服务都返回非常大的响应,因此响应需要相当长的时间才能返回(一个Web服务请求为8秒,另一个为12秒)。请求以串行方式运行而不是并行时,总执行时间为20秒。

有什么方法可以修改我的代码来异步请求两个Web服务,并且能够在接近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);
}

**感谢您的回复,我觉得这不是重复,因为我想停止执行我执行的两个线程,直到两者都收到了结果。以下解决方案显示了这一点**

4 个答案:

答案 0 :(得分:4)

非常简单的实现,为了获得更多进展,您可能需要查看FutureTask

    List<Thread> threadList = new ArrayList<>();
    threadList.add(new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                listOfCountries = service.getListOfCountries(host+"service/countries");
            } catch (Exception e) {
                log.error("Failed to read service: " + e);
            }
        }
    }));
    threadList.add(new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                listOfCities = service.getListOfCities(host+"service/cities");
            } catch (Exception e) {
                log.error("Failed to read service: " + e);
            }
        }
    }));
    for (Thread t:threadList ){
        t.start();
    }
    for (Thread t:threadList ){
        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //after both finish proceeds from here

注意字符串应该更全局地定义(类级别,而不是局部变量)

答案 1 :(得分:4)

我会尝试一些简单的事情,比如CompletableFuture

import java.util.concurrent.CompletableFuture;
...
final CompletableFuture<String> listOfCities = CompletableFuture.supplyAsync(() -> service.getListOfCities(...));
final CompletableFuture<String> listOfCountries = CompletableFuture.supplyAsync(() -> service. getListOfCountries(...));
final CompletableFuture<Void> allCompleted = CompletableFuture.allOf(listOfCities, listOfCountries);
allCompleted.thenRun(() -> {
    // whatever you want to do 
});

请参阅这些examples以供参考。

答案 2 :(得分:2)

班级的全局变量。

String listOfCities;
String listOfCountries; 

在函数中,这些方法将被调用,

try {//t is the object of the class like (Test t = new Test();)
    new Thread(()-> t.listOfCities = service.getListOfCities(host+"service/cities");).start();
    new Thread(()-> t.listOfCountries = service.getListOfCountries(host+"service/countries");).start();
} catch (Exception e) {
    log.error("Failed to read service: " + e);
}

代码示例Demo here

通过@AniketSahrawat

答案 3 :(得分:0)

如果您希望执行时间按完成顺序排列,我建议您使用 guava 中的ListenableFutureFutures.inCompletionOrder将完成这项工作。

示例用法可能如下所示:

ExecutorService es;
Callable<String> task1;
Callable<String> task2;
//...
ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(es);
List<ListenableFuture<String>> yourTasks = new ArrayList<>();
yourTasks.add(listeningExecutorService.submit(task1));
yourTasks.add(listeningExecutorService.submit(task2));
for(Future f: Futures.inCompletionOrder(yourTasks)){
   //process your task in completion order now
}