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
以便后续线程进入
这可能吗
# 1 楼答案
您已将
Future
添加到集合中。只需在下面添加代码块,通过调用带有超时周期的get()
来获取每个Future
任务的状态在我的例子中,超时是60秒。您可以根据您的要求进行更改
示例代码:
其他有用的员额:
How to forcefully shutdown java ExecutorService
How to wait for completion of multiple tasks in Java?
# 2 楼答案
我同意其中一条评论,您的执行器可以被不同的线程使用,这似乎很奇怪。通常,和执行器对于某个类的实例是私有的,但无论如何
您可以从文档中检查:
注意:这是一种阻塞方法,它将锁定线程池的工作线程并阻塞,直到计算完所有内容
并检查:
如果队列为空且activeCount为0,则所有任务都应已完成。我说应该,因为getActiveCount说“近似”。查看impl,这很可能是因为worker内部有一个标志指示它已锁定(正在使用)。从理论上讲,在执行和正在执行的工人之间,以及在标记自己之间,存在着一种轻微的竞争。 事实上,更好的方法是跟踪特征。你必须检查所有的未来和队列
然而,我认为你真正需要的是改变你的逻辑。与当前线程试图确定另一个线程是否同时提交了工作不同,您应该让另一个线程调用isShutdown(),在这种情况下不提交新任务
# 3 楼答案
你从错误的方向处理这个问题。如果您需要知道您的任务是否已完成,这意味着您的依赖项为->;B.执行人是确保依赖性的错误地点,因为你没有问你的汽车引擎“我们到了吗?”
Java提供了一些特性,以确保在启动新的执行路径之前已达到某个状态。其中之一是ExecutorService的invokeAll方法,它仅在所有已提交的任务完成时返回
# 4 楼答案
您可以通过对futureObjs中的所有未来对象调用isDone()方法进行检查。您需要确保在循环中调用isDone。对Future对象调用get()方法是另一个选项,因为get()是一个阻塞调用,所以只有在任务完成并且结果准备就绪后,它才会返回。但是,您真的想在所有任务完成后保持池开放吗