有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何确保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;
    }

但是,由于socket上的其他线程,可能会对EnqueueWork进行多次调用-我希望确保对.submit的调用在当前线程中完成,而不必关闭pool以便后续线程进入

这可能吗


共 (4) 个答案

  1. # 1 楼答案

    您已将Future添加到集合中。只需在下面添加代码块,通过调用带有超时周期的get()来获取每个Future任务的状态

    在我的例子中,超时是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?

  2. # 2 楼答案

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

    您可以从文档中检查:

    getActiveCount() - Returns the approximate number of threads that are >actively executing tasks.

    注意:这是一种阻塞方法,它将锁定线程池的工作线程并阻塞,直到计算完所有内容

    并检查:

    getQueue() - Returns the task queue used by this executor. Access to the task queue is intended primarily for debugging and monitoring. This queue may be in active use. Retrieving the task queue does not prevent queued tasks from executing.

    如果队列为空且activeCount为0,则所有任务都应已完成。我说应该,因为getActiveCount说“近似”。查看impl,这很可能是因为worker内部有一个标志指示它已锁定(正在使用)。从理论上讲,在执行和正在执行的工人之间,以及在标记自己之间,存在着一种轻微的竞争。 事实上,更好的方法是跟踪特征。你必须检查所有的未来和队列

    然而,我认为你真正需要的是改变你的逻辑。与当前线程试图确定另一个线程是否同时提交了工作不同,您应该让另一个线程调用isShutdown(),在这种情况下不提交新任务

  3. # 3 楼答案

    你从错误的方向处理这个问题。如果您需要知道您的任务是否已完成,这意味着您的依赖项为->;B.执行人是确保依赖性的错误地点,因为你没有问你的汽车引擎“我们到了吗?”

    Java提供了一些特性,以确保在启动新的执行路径之前已达到某个状态。其中之一是ExecutorService的invokeAll方法,它仅在所有已提交的任务完成时返回

    pool.invokeAll(listOfAllMyCallables);
    // if you reach this point all callables are completed
    
  4. # 4 楼答案

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