在使用 ThreadPoolExecutor 管理我的任务而不是为每个任务创建一个单独的线程之后。我使用以下部分来等待特定数量的任务完成:
poolThreadsExecutor.shutdown();
poolThreadsExecutor.awaitTermination(10, TimeUnit.MINUTES);
for (Future<List<String>> future : futures) {
if (!future.isDone()) {
future.cancel(true);
}
}
使用此代码,我确保在运行的任务完成之前无法提交新任务。正在运行的任务也有超时,之后我检查期货列表并取消任何任务,以防它被阻止。
有了这个解决方案,我就有了我想要的所有点,但问题是执行器之后会被销毁,我每次都必须创建一个新的。
是否有可能在不关闭执行器的情况下获得相同的功能?
PS:我也不能使用CoundDownLatch,因为任务的数量以前是未知的。
这将是一个解决方案的大纲:
- 计算任务完成的截止日期:
deadline = currentTimeMillis() + timeout
; - 遍历所有期货,调用
future.get(timeLeft, MILLISECONDS)
,每次调整timeLeft = deadline - currentTimeMillis()
; - 如果达到截止日期,则打破此循环并进入取消循环。
final long deadline = System.currentTimeMillis() + timeout;
for (Future<?> f : futures) {
final long timeLeft = deadline - System.currentTimeMillis();
if (timeLeft <= 0) break;
try {
f.get(timeLeft, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
break;
}
}
for (Future<?> f : futures) {
if (!future.isDone()) {
future.cancel(true);
}
}
你是如何提交任务的。但我看到你有一个期货清单。如果可以一次提交所有任务,则可以使用:
futures = poolThreadsExecutor.invokeAll(tasks, 10, TimeUnit.MINUTES);
它将执行您的任务,直到全部完成或超时到期(尚未完成的任务将被取消)。
此外,来自番石榴的Futures.successAsList可能会有所帮助。