繁体   English   中英

如何等待所有线程完成

[英]How to wait for all threads to complete

我创建了一些工作流程,如何等待我创建的所有线程。 此示例在99%的情况下都有效,但是有时方法waitForAllDone会在所有线程完成后尽快完成。 我知道这是因为在waitForAllDone之后,我正在关闭正在使用创建的线程的流,因此发生异常

Caused by: java.io.IOException: Stream closed

我的线程开始于:

  @Override
  public void run() {
    try {
      process();
    } finally {
      Factory.close(this);
    }
  }

闭幕:

  protected static void close(final Client client) {
    clientCount--;
  }

当我创建线程时,我称之为:

  public RobWSClient getClient() {
    clientCount++;
    return new Client();
  }

和clientCount变量在工厂内部:

  private static volatile int clientCount = 0;

等待:

  public void waitForAllDone() {
    try {
      while (clientCount > 0) {
        Thread.sleep(10);
      }

    } catch (InterruptedException e) {
      LOG.error("Error", e);
    }
  }

你需要保护的修改和读取clientCount通过synchronized 主要问题是clientCount--clientCount++不是原子操作,因此两个线程可以执行clientCount-- / clientCount++并导致错误的结果。

如果您在该字段上进行的所有操作都是原子操作,则仅按照上述操作简单地使用volatile 由于它们不是,因此您需要使用一些锁定机制。 正如Anton所说, AtomicInteger是这里的绝佳选择。 请注意,它应该是finalvolatile以确保它不是线程本地的。

话虽如此,Java 1.5的一般规则是使用ExecutorService而不是Threads 将此功能与Guava的Futures类结合使用,可以使等待所有人完成的过程变得非常简单:

Future<List<?>> future = Futures.successfulAsList(myFutureList);
future.get();
// all processes are complete

Futures.successfulAsList

我不确定您的其余代码是否没有问题,但是您不能像这样增加volatile变量clientCount++ ; 改用AtomicInteger

等待线程终止的最佳方法是使用高级并发工具之一。 在这种情况下,最简单的方法是使用ExecutorService。

您可以通过以下方式将新任务“提供”给执行者:

...
ExecutorService executor = Executors.newFixedThreadPool(POOL_SIZE);
...

Client client = getClient(); //assuming Client implements runnable
executor.submit(client);
...

public void waitForAllDone() {
    executor.awaitTermination(30, TimeUnit.SECOND) ; wait termination of all threads for 30 secs
... 
}

这样,您就不会在繁忙的等待或睡眠/唤醒周期中浪费宝贵的CPU周期。 有关详细信息,请参见ExecutorService文档。

暂无
暂无

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

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