【发布时间】:2021-10-02 10:13:45
【问题描述】:
我需要同时调用几个(少于 30 个)REST API,并立即返回我从这些 API 调用中获得的第一个响应。
我实现了一个这样的方法:
public String fetchFastest(List<URL> urls) throws ExecutionException, InterruptedException {
var executor = Executors.newFixedThreadPool(urls.size());
var futures = new ArrayList<Future<String>>();
urls.forEach(url -> {
futures.add(
executor.submit(() -> getResponse(url)) // performs a http request with timeout and returns the response (or null in the case of failure)
);
});
var failed = new ArrayList<Future<String>>();
while (failed.size() < futures.size()) {
for(var f: futures) {
if(f.isDone() && !failed.contains(f)) {
if(f.get() == null) {
failed.add(f);
}
else {
executor.shutdownNow();
return f.get();
}
}
}
}
throw new RuntimeException("No response.");
}
这种方法似乎奏效了。但是,鉴于此方法被频繁调用,并且创建线程池是一项昂贵的任务(我正在为每个方法调用创建一个),我想知道我是否可以以某种方式改进这种方法或找到其他更快的解决方案计算成本更低。
欢迎提出任何建议。提前谢谢你。
【问题讨论】:
-
我会先取出线程池并共享一个,而不是每次都创建新的。您还需要添加工具来衡量性能,以便判断您所做的更改是否有效。
-
这个方法会被并发调用吗?
标签: java multithreading concurrency