简体   繁体   English

我怎样才能知道ThreadPoolExecutor中的线程已经完成?

[英]How can I tell that threads in ThreadPoolExecutor are done?

I am writing code where I need to make sure that no threads are currently running in a thread pool before I commit results (to avoid losing data I should have put in the commit). 我正在编写代码,以确保在提交结果之前,线程池中当前没有任何线程正在运行(为避免丢失数据,我应该将其放入提交中)。 For that, I'm using: 为此,我正在使用:

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

But a colleague pointed out in review that the doc for getActiveCount states: 但是一位同事在评论中指出,getActiveCount的文档指出:

  • Returns the approximate number of threads that are actively 返回活跃线程的大概数量
  • executing tasks. 执行任务。

So, is there a risk I would get out of the while loop while there are still active threads in the pool? 因此,在池中仍然有活动线程的情况下,是否存在退出while循环的风险? If so, what would be the correct way to wait for all my worker threads to be done? 如果是这样,等待我所有工作线程完成的正确方法是什么?

Edit: To give some more context : this is an online system, where the task that contains the executor service is left running indefinitely. 编辑:提供更多上下文 :这是一个联机系统,其中包含执行程序服务的任务将无限期运行。 Work comes in via a messaging system, is put on a thread in the executor, which doesn't need any synchronization, and works come out into another queue for the messaging system. 工作通过消息传递系统进入,放置在执行程序中的线程上,不需要任何同步,并且工作进入消息传递系统的另一个队列。 I don't want to kill the executor to wait for completion of tasks. 我不想杀死执行程序以等待任务完成。

You might want to consider using a CompletionService ( http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CompletionService.html ). 您可能要考虑使用CompletionServicehttp://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CompletionService.html )。

A CompletionService wraps an ExecutorService and returns a Future when tasks are submitted. CompletionService包装ExecutorService并在提交任务时返回Future By maintaining a list of these Future s, you can see if the jobs that you're waiting on have completed. 通过维护这些Future的列表,您可以查看正在等待的作业是否已经完成。 It also has the additional advantage that you can have others use the same ExecutorService since you have some means of accounting, 它还具有其他优势,因为您可以使用某些会计方法,因此可以让其他人使用相同的ExecutorService

_executor.awaitTermination(); should do the job. 应该做的工作。 Now, it won't actually wait for the threads to shutdown, but rather it would wait for all available tasks to terminate. 现在,它实际上不会等待线程关闭,而是会等待所有可用任务终止。

You could also provide keepAliveTime to a thread pool constructor to instantly terminate idle threads: 您还可以向线程池构造函数提供keepAliveTime ,以立即终止空闲线程:

ExecutorService executor = new ThreadPoolExecutor(0, 10, 0L /* keepAlive */, 
        TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

To notify a thread that it should clean up and terminate, use the interrupt method. 若要通知线程应清除并终止,请使用interrupt方法。 t.interrupt(); t.interrupt();

and it is good to print or have log of your errors from catch block. 并且可以从catch块打印或记录错误日志。

When tasks are submitted to the executor, they return Futures, which indicate when they complete. 当任务提交给执行者时,它们将返回Future,后者指示它们何时完成。 That is the preferred mechanism to use. 那是首选的使用机制。

You can use JDK ExecutorService shutdown/awaitTermination. 您可以使用JDK ExecutorService关闭/ awaitTermination。

Use case: need to cleanup thread-locals in pool threads upon their completion and this cleanup can take long (eg connection close). 用例:需要在池线程完成后清除线程中的线程局部,这种清除可能需要很长时间(例如,连接关闭)。 Only after that the main thread can continue. 之后,主线程才能继续。

A worker thread can register itself in some collection. 工作线程可以在某些集合中注册自己。 For that override start() and run() and pass a custom thread factory to ThreadPoolExecutor : 为此,覆盖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);
        }
    }

    ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM