问题描述
我创建了一些工作流程,如何等待我创建的所有线程.此示例在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
是一个很好的选择.请注意,它应该是final
或volatile
,以确保它不是线程本地的.
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
这篇关于如何等待所有线程完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!