如何等待所有线程完成 [英] How to wait for all threads to complete

查看:183
本文介绍了如何等待所有线程完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I created some workflow how to wait for all thread which I created. This example works in 99 % of cases but sometimes method waitForAllDone is finished sooner then all thread are completed. I know it because after waitForAllDone I am closing stream which is using created thread so then occurs exception

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--;
  }

当我创建线程时,我将其称为:

when I creating thread I call this:

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

和工厂内部的clientCount变量:

and clientCount variable inside factory:

  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++并最终得到错误的结果.

You need to protect the modification and reading of clientCount via synchronized. The main issue is that clientCount-- and clientCount++ are NOT an atomic operation and therefore two threads could execute clientCount-- / clientCount++ and end up with the wrong result.

仅当字段上的所有操作都是原子操作时,才像上面一样使用volatile即可.由于它们不是,因此您需要使用一些锁定机制.正如安东所说,AtomicInteger是一个很好的选择.请注意,它应该是finalvolatile,以确保它不是线程本地的.

Simply using volatile as you do above would ONLY work if ALL operations on the field were atomic. Since they are not, you need to use some locking mechanism. As Anton states, AtomicInteger is an excellent choice here. Note that it should be either final or volatile to ensure it is not thread-local.

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

That being said, the general rule post Java 1.5 is to use a ExecutorService instead of Threads. Using this in conjuction with Guava's Futures class could make waiting for all to complete to be as simple as:

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

查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆