如何判断ThreadPoolExecutor中的线程是否已完成?

时间:2013-12-18 16:48:41

标签: java concurrency threadpool

我正在编写代码,我需要确保在提交结果之前当前没有线程在线程池中运行(以避免丢失我应该放在提交中的数据)。为此,我使用:

while (_executor.getActiveCount() > 0)
{
  try
  {
    Thread.sleep(10); // milliseconds
  }
  catch (InterruptedException e)
  {
    // OK do nothing
  }
}

但是一位同事在评论中指出getActiveCount的文档声明:

  
      
  • 返回主动
  • 的近似线程数   
  • 执行任务。
  •   

那么,当池中仍然存在活动线程时,是否存在从while循环中退出的风险?如果是这样,等待所有工作线程完成的正确方法是什么?

编辑:提供更多上下文:这是一个在线系统,其中包含执行程序服务的任务将无限期地运行。工作通过消息传递系统进入,放在执行程序中的一个线程上,该线程不需要任何同步,并且工作进入消息传递系统的另一个队列。我不想杀死执行者等待完成任务。

5 个答案:

答案 0 :(得分:4)

您可能需要考虑使用CompletionServicehttp://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);
        }
    }

    ...