Java 任务完成或超时时执行线程池检查
我使用的是executorservice,每个webservice调用产生大约9-10个可调用的任务,并提交给executorservice线程池。应用程序有1个单一Executor服务,线程池大小为100。 当我提交可调用项时,我有一个2 For循环。外部循环运行到指定的超时过期或完成hashset size==提交的任务大小;内部循环遍历可调用项,如果isDone()==true,则这些被收集到一个“完成的”hashset中。当outerloop条件失败时,我循环“Completed”hashset中的可调用项并聚合结果。 问题是我确信有一个比使用两个循环更优雅的解决方案Java 任务完成或超时时执行线程池检查,java,multithreading,concurrency,executorservice,Java,Multithreading,Concurrency,Executorservice,我使用的是executorservice,每个webservice调用产生大约9-10个可调用的任务,并提交给executorservice线程池。应用程序有1个单一Executor服务,线程池大小为100。 当我提交可调用项时,我有一个2 For循环。外部循环运行到指定的超时过期或完成hashset size==提交的任务大小;内部循环遍历可调用项,如果isDone()==true,则这些被收集到一个“完成的”hashset中。当outerloop条件失败时,我循环“Completed”has
如果所有任务都已完成或超时过期,那么通知我的最佳方式是什么?任何框架、库等或设计模式?您基本上有两种选择,拉或推 Pull是您已经尝试过的-发送所有异步任务,保留对它们的引用并调用isDone(),直到它们全部完成 另一方面,推送将调用和通知任务分开。您将调用异步任务,然后该方法将立即返回。通知将由任务本身处理,他们需要在工作完成时通知 此通知可以很容易地由实现,或者如果您使用的是JavaEE 我个人更喜欢push方法,因为它清理代码,分离调用任务和处理结果的关注点。不过,任何一种方法都可以。您可以使用它
- 执行
在CompletableFuture.supplySync()中的任务
哈希集中收集这些任务
- 使用
thenCombine()
- 在聚合上,使用超时执行
,如果发生get()
,则使用默认值完成所有计算。然后聚合将立即返回部分结果TimeoutException
CompletableFuture
类为您完成的
示例(使用整数和作为聚合)
publicstaticvoidmain(字符串[]args){
ExecutorService ExecutorService=Executors.newFixedThreadPool(10);
集合计算=新的HashSet();
CompletableFuture总和=CompletableFuture.completedFuture(0);
对于(int i=0;i<100;i++){
//提交到线程池
完全未来计算=
CompletableFuture.supplyAsync(CompletableFutureGather::longCalculation,executorService);
计算。添加(计算);
sum=sum.thenCombine(计算,整数::sum);//设置将来的聚合
}
int-total=0;
试一试{
total=sum.get(5,TimeUnit.SECONDS);//设置超时
}捕捉(中断异常e){
Thread.currentThread().interrupt();
}捕获(执行例外){
抛出(RuntimeException)e.getCause();
}捕获(超时异常e){
//使用默认值抢先完成计算,已完成的计算将不受影响
计算.forEach(integercompleteFuture->integercompleteFuture.complete(0));
total=sum.getNow(0);//一切都已完成,因此将立即返回部分聚合
}
系统输出打印项次(总计);
}
私有静态整数计算(){
试一试{
睡眠(5000);
}捕捉(中断异常e){
Thread.currentThread().interrupt();
}
返回1;
}
我同意推送模式,Google guava甚至提供了一些带有回调支持的库UTIL,但我的要求不仅仅是计算任务的完成情况,而是在一段时间后超时,不管完成了多少任务。我认为推送模式也简化了超时。您只需启动计时器,并在设定的时间量后检查观察者。如果观察者没有收集到所有的响应,那么您可以处理超时。因此,观察者是一个循环中的进程,有一个睡眠时间,它会定期检查进度,直到某个时间。。。嗯..更优雅的解决方案是什么?您只指定了一个实现,而不是一个问题。
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
Set<CompletableFuture<Integer>> calculations = new HashSet<>();
CompletableFuture<Integer> sum = CompletableFuture.completedFuture(0);
for (int i = 0; i < 100; i++) {
// submit to thread pool
CompletableFuture<Integer> calculation =
CompletableFuture.supplyAsync(CompleteableFutureGather::longCalculation, executorService);
calculations.add(calculation);
sum = sum.thenCombine(calculation, Integer::sum); // set up future aggregation
}
int total = 0;
try {
total = sum.get(5, TimeUnit.SECONDS); // set timeout
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
throw (RuntimeException) e.getCause();
} catch (TimeoutException e) {
// preemptively complete calculations with default value, those already completed will be unaffected
calculations.forEach(integerCompletableFuture -> integerCompletableFuture.complete(0));
total = sum.getNow(0); // everything is complete so partial aggregation will be returned immediately
}
System.out.println(total);
}
private static Integer longCalculation() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return 1;
}