Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 任务完成或超时时执行线程池检查_Java_Multithreading_Concurrency_Executorservice - Fatal编程技术网

Java 任务完成或超时时执行线程池检查

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

我使用的是executorservice,每个webservice调用产生大约9-10个可调用的任务,并提交给executorservice线程池。应用程序有1个单一Executor服务,线程池大小为100。 当我提交可调用项时,我有一个2 For循环。外部循环运行到指定的超时过期或完成hashset size==提交的任务大小;内部循环遍历可调用项,如果isDone()==true,则这些被收集到一个“完成的”hashset中。当outerloop条件失败时,我循环“Completed”hashset中的可调用项并聚合结果。 问题是我确信有一个比使用两个循环更优雅的解决方案


如果所有任务都已完成或超时过期,那么通知我的最佳方式是什么?任何框架、库等或设计模式?

您基本上有两种选择,

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;
}