我正在编写代码,我需要确保在提交结果之前当前没有线程在线程池中运行(以避免丢失我应该放在提交中的数据)。为此,我使用:
while (_executor.getActiveCount() > 0)
{
try
{
Thread.sleep(10); // milliseconds
}
catch (InterruptedException e)
{
// OK do nothing
}
}
但是一位同事在评论中指出getActiveCount的文档声明:
- 返回主动
的近似线程数- 执行任务。
那么,当池中仍然存在活动线程时,是否存在从while循环中退出的风险?如果是这样,等待所有工作线程完成的正确方法是什么?
编辑:提供更多上下文:这是一个在线系统,其中包含执行程序服务的任务将无限期地运行。工作通过消息传递系统进入,放在执行程序中的一个线程上,该线程不需要任何同步,并且工作进入消息传递系统的另一个队列。我不想杀死执行者等待完成任务。
答案 0 :(得分:4)
您可能需要考虑使用CompletionService
(http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CompletionService.html)。
CompletionService
包装ExecutorService
并在提交任务时返回Future
。通过维护这些Future
的列表,您可以查看您正在等待的作业是否已完成。它还有一个额外的好处,你可以让其他人使用相同的ExecutorService
,因为你有一些会计方法,
答案 1 :(得分:1)
_executor.awaitTermination();
应该做的工作。现在,它实际上不会等待线程关闭,而是等待所有可用任务终止。
您还可以向线程池构造函数提供keepAliveTime
以立即终止空闲线程:
ExecutorService executor = new ThreadPoolExecutor(0, 10, 0L /* keepAlive */,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
答案 2 :(得分:0)
要通知线程它应该清理并终止,请使用中断方法。 的 t.interrupt(); 强>
最好从catch块打印或记录错误。
答案 3 :(得分:0)
当任务提交给遗嘱执行人时,他们会返回期货,这表明它们何时完成。这是首选使用的机制。
您可以使用JDK ExecutorService shutdown / awaitTermination。
答案 4 :(得分:0)
用例:需要在完成后清理池线程中的线程本地,并且这种清理可能需要很长时间(例如连接关闭)。只有在那之后主线程才能继续。
工作线程可以在某个集合中注册自己。对于覆盖start()
和run()
并将自定义线程工厂传递给ThreadPoolExecutor
:
class MyThreadFactory implements ThreadFactory {
@Override
public Thread newThread(final Runnable r) {
return new MyThread(r);
}
...
class Some {
void waitAllThreads() {
Thread worker;
while ((worker = workerThreads.poll()) != null) {
worker.join();
}
}
...
class MyThread extends Thread {
@Override
public synchronized void start() {
if (getState() == State.NEW) {
some.workerThreads.offer(this);
}
super.start();
}
@Override
public void run() {
try {
super.run();
} finally {
some.workerThreads.remove(this);
}
}
...