java - 如何等待所有线程完成

标签 java multithreading

我创建了一些工作流程如何等待我创建的所有线程。此示例适用于 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);
    }
  }

最佳答案

您需要通过synchronized保护clientCount的修改和读取。主要问题是 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

关于java - 如何等待所有线程完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13473070/

相关文章:

java - 如何对 Map<String, List<Summary>> 进行排序

c# - 使用 System.Threading.Task 访问 winform 控件卡住

c++ - 如何将两个值相乘并以原子方式存储结果?

java - 从 macOS 系统设置中获取日期和时间格式

java.time.format.DateTimeParseException : Text could not be parsed at index 21

java - 多次重装JDK后出现JNL错误

c++ - 避免 GUI 在多线程操作时卡住

android - 从 iOS 中的 ([self performSelectorOnMainThread]) 等非 Activity 对象访问 UI-Thread

multithreading - 了解协程

java - 在 Android Studio 中将 EditText 保存到 ArrayList - 编辑 1