[英]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
是這里的絕佳選擇。 請注意,它應該是final
或volatile
以確保它不是線程本地的。
話雖如此,Java 1.5的一般規則是使用ExecutorService
而不是Threads
。 將此功能與Guava的Futures
類結合使用,可以使等待所有人完成的過程變得非常簡單:
Future<List<?>> future = Futures.successfulAsList(myFutureList);
future.get();
// all processes are complete
我不確定您的其余代碼是否沒有問題,但是您不能像這樣增加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.