目前,我确保我的任务已经完成,然后继续前进:
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
。
这可能吗?
答案 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();
}
其他有用的帖子:
答案 3 :(得分:0)
您正在从错误的方向接近此问题。如果您需要知道您的任务是否已完成,则表示您具有A-> B的依赖关系。执行者是错误的地方,以确保依赖,就像你没有问你的汽车引擎“我们还在吗?”。
Java提供了几个功能,以确保在开始新的执行路径之前已达到某个状态。其中之一是ExecutorService的invokeAll方法,只有在完成所有已提交的任务后才会返回。
pool.invokeAll(listOfAllMyCallables);
// if you reach this point all callables are completed