[英]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.