首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java Clear CompletionService工作队列

Java Clear CompletionService工作队列
EN

Stack Overflow用户
提问于 2021-06-16 04:26:32
回答 1查看 24关注 0票数 0

我正在编写一个程序,它使用CompletionService对一堆不同的对象运行线程分析,其中每个“分析”都包括接受一个字符串并进行一些计算,以得到truefalse作为答案。我的代码基本上是这样的:

代码语言:javascript
复制
// tasks come from a different method and contain the strings + some other needed info
List<Future<Pair<Pieces,Boolean>>> futures = new ArrayList<>(tasks.size());
for (Task task : tasks) {
    futures.add(executorCompletionService.submit(task));
}
ArrayList<Pair<Pieces, Boolean>> pairs = new ArrayList<>();

int toComplete = tasks.size();
int received = 0;
int failed = 0;
while (received < toComplete) {
    Future<Pair<Pieces, Boolean>> resFuture = executorCompletionService.take();
    received++;
    Pair<Pieces, Boolean> res = resFuture.get();
    if (!res.getValue()) failed++;
    if (failed > 300) {
        // My problem is here
    }

    pairs.add(res);
}

// return pairs and go on to do something else

在标记的部分中,我的目标是如果超过300个字符串失败,就让它放弃计算,这样我就可以继续进行新的分析,使用一些不同的数据再次调用此方法。问题是,由于相同的CompletionService被再次使用,如果我不以某种方式清除队列,那么工作队列将继续增长,因为我每次使用它时都会不断添加更多(因为在300次失败之后,可能仍然有许多未处理的字符串)。

我试图遍历futures列表并使用类似futures.foreach(future -> future.cancel(true)的东西删除所有未完成的任务,但是当我下一次调用该方法时,当我试图调用resFuture.get()时,我得到了一个java.util.concurrent.CancellationException错误。

(编辑:看起来即使我调用了foreach(future->future.cancel(true)),这也不能保证之后的workerQueue实际上是清晰的。我不明白为什么会这样。看起来似乎需要一段时间才能清除队列,并且代码不会等待这种情况发生后再进行下一次分析,因此偶尔会在已取消的未来调用get。)

我也试着去做

代码语言:javascript
复制
            while (received < toComplete) {
                executorCompletionService.take();
                received++;
            }

清空队列,虽然这是可行的,但它比直接运行所有分析的速度要快不了多少,因此它不能很好地提高效率。

我的问题是,是否有更好的方法清空工作队列,这样当我下一次调用此代码时,就好像CompletionService又是新的一样。

编辑:我尝试过的另一种方法是设置executorCompletionService = new CompletionService,这比我的其他解决方案稍微快一点,但仍然相当慢,肯定不是很好的做法。

附言:我也很高兴接受任何其他可能的方式,我不喜欢使用CompletionService,这是迄今为止我所做的最简单的事情

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-17 13:21:47

这个问题已经解决了,但我看到其他类似的问题没有好的答案,所以这是我的解决方案:

以前,我使用ExecutorService来创建我的ExecutorCompletionService(ExecutorService)。我把ExecutorService换成了ThreadPoolExecutor,因为在后台的ExecutorService已经是ThreadPoolExecutor了,所以所有的方法签名都可以通过强制转换来修复。使用ThreadPoolExecutor可以在后端提供更多的自由,特别是你可以调用threadPoolExecutor.getQueue().clear()来清除所有等待完成的任务。最后,我需要确保“排出”剩余的工作任务,所以我的最终取消代码如下所示:

代码语言:javascript
复制
        if (failed > maxFailures) {
           executorService.getQueue().clear();
           while (executorService.getActiveCount() > 0) {
               executorCompletionService.poll();
           }

在此代码块结束时,executor将准备再次运行。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67993058

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档