簡體   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