如何等待ThreadPoolExecutor完成

ken*_*dds 30 java multithreading threadpool

我的问题:如何在a上执行一堆线程对象ThreadPoolExecutor并等待它们全部完成然后再继续?

我是ThreadPoolExecutor的新手.因此,此代码是一项测试,以了解它是如何工作的.现在我甚至没有填充BlockingQueue对象,因为我不知道如何启动队列而不用execute()另一个调用RunnableObject.无论如何,现在我只是打电话,awaitTermination()但我想我仍然缺少一些东西.任何提示都会很棒!谢谢.

public void testThreadPoolExecutor() throws InterruptedException {
  int limit = 20;
  BlockingQueue q = new ArrayBlockingQueue(limit);
  ThreadPoolExecutor ex = new ThreadPoolExecutor(limit, limit, 20, TimeUnit.SECONDS, q);
  for (int i = 0; i < limit; i++) {
    ex.execute(new RunnableObject(i + 1));
  }
  ex.awaitTermination(2, TimeUnit.SECONDS);
  System.out.println("finished");
}
Run Code Online (Sandbox Code Playgroud)

RunnableObject类:

package playground;

public class RunnableObject implements Runnable {

  private final int id;

  public RunnableObject(int id) {
    this.id = id;
  }

  @Override
  public void run() {
    System.out.println("ID: " + id + " started");
    try {
      Thread.sleep(2354);
    } catch (InterruptedException ignore) {
    }
    System.out.println("ID: " + id + " ended");
  }
}
Run Code Online (Sandbox Code Playgroud)

Old*_*eon 48

你应该循环 awaitTermination

ExecutorService threads;
// ...
// Tell threads to finish off.
threads.shutdown();
// Wait for everything to finish.
while (!threads.awaitTermination(10, TimeUnit.SECONDS)) {
  log.info("Awaiting completion of threads.");
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么要循环?为什么不增加等待它的秒数.通常我会做一个`awaitTermination(Long.MAX_VALUE,TimeUnit.SECONDS)`等等. (10认同)
  • 我喜欢while循环,因为我有一个执行任务处理文件的任务,并且他们需要完成的时间是未知的(取决于文件的数量) (2认同)

Gra*_*ray 5

您的问题似乎是shutdown在将所有作业提交到池之后您没有打电话。没有shutdown()你的awaitTermination意志总会返回false。

ThreadPoolExecutor ex =
    new ThreadPoolExecutor(limit, limit, 20, TimeUnit.SECONDS, q);
for (int i = 0; i < limit; i++) {
  ex.execute(new RunnableObject(i + 1));
}
// you are missing this line!!
ex.shutdown();
ex.awaitTermination(2, TimeUnit.SECONDS);
Run Code Online (Sandbox Code Playgroud)

您还可以执行以下操作来等待所有作业完成:

List<Future<Object>> futures = new ArrayList<Future<Object>>();
for (int i = 0; i < limit; i++) {
  futures.add(ex.submit(new RunnableObject(i + 1), (Object)null));
}
for (Future<Object> future : futures) {
   // this joins with the submitted job
   future.get();
}
...
// still need to shutdown at the end
ex.shutdown();
Run Code Online (Sandbox Code Playgroud)

另外,由于您正在睡眠数2354毫秒,但仅等待终止所有作业2 SECONDSawaitTermination因此总是会返回false

最后,听起来您担心要创建一个新文件ThreadPoolExecutor,而想重用第一个。不用了 与您编写用来检测作业是否完成的任何代码相比,GC开销将极小。


引用javadocs ThreadPoolExecutor.shutdown()

启动有序关闭,在该关闭中执行先前提交的任务,但不接受任何新任务。如果已关闭,则调用不会产生任何其他影响。

在该ThreadPoolExecutor.awaitTermination(...)方法中,它正在等待执行程序的状态进入TERMINATED。但首先,国家必须去SHUTDOWN,如果shutdown()被调用或STOP如果shutdownNow()被调用。