如何确保ExecutorService池已完成,而不关闭它?

时间:2015-12-04 08:13:47

标签: java multithreading executorservice

目前,我确保我的任务已经完成,然后继续前进:

    ExecutorService pool = Executors.newFixedThreadPool(5);

    public Set<Future> EnqueueWork(StreamWrapper stream) {
        Set<Future> futureObjs = new HashSet<>();
        util.setData(stream);
        Callable callable = util;

        Future future = pool.submit(callable);
        futureObjs.add(future);

        pool.shutdown();
        try {
            pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Node.sendTCP(Node.getNodeByHostname(StorageTopology.getNextPeer()), Coordinator.prepareForTransport(stream));

        return futureObjs;
    }

但是,由于我的套接字上有一些其他线程,可能会对EnqueueWork进行多次调用 - 我想确保在当前线程中完成对.submit的调用,没有关闭后续线程的pool

这可能吗?

4 个答案:

答案 0 :(得分:2)

您可以通过在futureObjs中的所有Future对象上调用isDone()方法来检查。您需要确保在循环中调用isDone。在Future对象上调用get()方法是另一种选择,因为get()是一个阻塞调用,它只在任务完成且结果准备好后才返回。但是你真的想在所有任务完成后保持游泳池开放吗?

答案 1 :(得分:0)

我同意其中一条评论,你的执行程序可以被不同的线程使用似乎很奇怪。通常,执行程序对某个类的实例是私有的,但无论如何。

您可以从文档中检查:

  

getActiveCount() - 返回&gt;主动执行任务的近似线程数。

注意:这是一种阻止方法,它会锁定你的线程池的worker并阻塞它直到它计算了所有内容

并检查:

  

getQueue() - 返回此执行程序使用的任务队列。访问        任务队列主要用于调试和监视。        此队列可能正在使用中。检索任务队列        不会阻止排队的任务执行。

如果您的队列为空并且activeCount为0,则的所有任务应该已完成。我说应该因为getActiveCount说&#34;近似&#34;。查看impl,这很可能是因为worker在内部有一个标志,表明它已被锁定(正在使用中)。理论上,在执行和完成工作之间存在轻微的竞争,并且标记自己。 事实上,更好的方法是跟踪功能。您必须检查队列并确保所有未来都已完成。

但是我认为你真正需要的是扭转你的逻辑。如果另一个线程在此期间提交了工作,而不是当前线程尝试解决问题,那么您应该让另一个线程调用isShutdown()并且在这种情况下根本不提交新任务。

答案 2 :(得分:0)

您已将Future添加到该集。只需添加以下代码块,即可通过在超时期限内调用Future来获取每个get()任务的状态。

在我的例子中,超时是60秒。您可以根据自己的要求进行更改。

示例代码:

        try{
            for(Future future : futureObjs){
            System.out.println("future.status = " + future.get(60000, TimeUnit.MILLISECONDS));
            }
        }catch(Exception err){
            err.printStackTrace();
        }

其他有用的帖子:

How to forcefully shutdown java ExecutorService

How to wait for completion of multiple tasks in Java?

答案 3 :(得分:0)

您正在从错误的方向接近此问题。如果您需要知道您的任务是否已完成,则表示您具有A-> B的依赖关系。执行者是错误的地方,以确保依赖,就像你没有问你的汽车引擎“我们还在吗?”。

Java提供了几个功能,以确保在开始新的执行路径之前已达到某个状态。其中之一是ExecutorService的invokeAll方法,只有在完成所有已提交的任务后才会返回。

pool.invokeAll(listOfAllMyCallables);
// if you reach this point all callables are completed