我试图实现的一个想法如下。
- 我有 1000 个网址可供下载数据,以便将其用于后期处理(例如,计算一些统计数据)。 我实际上并不需要成功完成所有下载,但需要尽可能多。
- 我认为某些位置可能不可用,要么没有响应任何有值(value)的内容(例如 HTTP 503),要么花费超过 TO=10 秒的时间来处理请求。
- 我有 T=5 个线程来并行处理 URL,为每个线程提供相同的超时 TO。
- 一旦完成(我预计会比 TO 更早发生),我会汇总一些统计数据(这是一个非常快的操作)并开始下一次下载(如果有)。
到目前为止我想出的解决方案是
ExecutorService executorService = Executors.newFixedThreadPool(T);
ExecutorCompletionService<MyResult> completionService = new ExecutorCompletionService<>(executorService);
urls.forEach(url -> {
Callable<MyResult> callable = () -> new MyResult(url);
completionService.submit(callable);
});
for (int i = 0; i < urls.size(); i++) {
Future<MyResult> resultFuture = completionService.poll(TO, TimeUnit.SECONDS);
if (resultFuture == null)
continue;
MyResult myResult = resultFuture.get();
myAggregate(myResult.getRate());
}
看起来我正在努力实现一些目标。但它既不会为每次下载提供相同的超时时间,也不会正确取消 future 。那么,正确的解决方案是什么?
最佳答案
尝试使用invokeAll方法,只需将Callables放入列表中,然后在ExecutorService上调用invokeAll(),将超时作为第二个和第三个参数。
executorService.invokeAll(callableList, 20, TimeUnit.SECONDS);
关于java - 如何使用几个线程完成大量作业,并为每个线程提供相同的超时完成时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42021951/