我相信我面临的问题是嵌套式监视器锁定的变体。基本上我有两组线程(不是ThreadGroups,只是逻辑组)。一组线程(假设后台组)将等待一个对象,而另一组线程正在工作(工作组)。工作线程一个接一个地完成,直到最后一个工作线程处于'完整'方法中。我想要做的是找出告诉这个最后一个工作线程要等待的方法,然后然后调用notifyAll()来唤醒所有后台线程。正如您可能猜到的那样,两组线程正在来回切换 - 一组正在工作而另一组正在等待,然后组切换。问题是,如果我在当前等待的线程上发出notifyAll(),则无法保证最终工作线程将在通知线程完成之前进入wait()调用并尝试启动下一次交换。
很抱歉,如果这个问题有点过时 - 似乎我对并发的工作越多,我的代码就越复杂:(
答案 0 :(得分:2)
听起来你需要类似Gate类的东西,它由两个CountDownLatch实例组成。我在很多多线程测试中使用类似的东西。
您的等待线程全部呼叫gate.ready()
,工作人员完成后呼叫gate.go()
请注意,此特定实现假定1个协调器线程。要支持更多,只需使用您需要的服务器线程数构造go
锁存器。
/**
* Simple starting gate for co-ordinating a bunch of threads.
*/
final class Gate {
final CountDownLatch ready;
final CountDownLatch go = new CountDownLatch(1);
Gate(final int threads) {
ready = new CountDownLatch(threads);
}
/**
* Called from the racing threads when ready. They will then block until all
* threads are at this point;
*/
void ready() {
ready.countDown();
await(go);
}
/**
* Called from the starter thread. Blocks until everybody is ready, and then
* signals go.
*/
void go() {
await(ready);
go.countDown();
}
static void await(final CountDownLatch latch) {
try {
if (!latch.await(5, TimeUnit.SECONDS)) { // arbitrary, parameterise for production use
throw new TimedOutException()
}
} catch (final InterruptedException e) {
throw new RuntimeException(e);
}
}
static final class TimedOutException extends IllegalStateException {}
}
如果您需要未知的任意线程数,您可能需要类似Doug Lea的Phaser
类来自Java7。
答案 1 :(得分:1)
您可以尝试使用Exchanger连接线程组。它通常用于在两个交替工作的线程之间来回传输工作。如果您可以使转移工作正常,您似乎也可以使其适用于线程组。
如果每个组都有一个控制器线程怎么办?然后,当他在Exchanger中收到一个项目,然后加入他自己的所有组时,您可以让控制器notifyAll在他的组中。当连接全部返回时,他可以将控制权转移回交换器。
或者如果每个组中的线程数是固定的,您可以为具有固定线程数的组创建CyclicBarrier,然后指定在所有线程完成并命中时要运行的屏障操作障碍。该操作可以通过Exchanger或SynchronousQueue(这是一个强制执行同步协调的0长队列)来转移控制。
有关同步器的详细信息,请查看Java Concurrency in Practice或DZone concurrency refcard。
答案 2 :(得分:0)
也许您可以使用一些变量来指示仍在工作的线程数。因此,当线程完成时,它使用以下方法:
synchronized void completed() { threads_working--; if (threads_working == 0) { synchronized (some_lock) { some_lock.notifyAll(); } } }
每个线程在开始工作时都会增加该数字。
答案 3 :(得分:0)
是否可以允许线程返回并终止而不是让它们等待?如果是这样,您是否考虑过实现线程管理器来生成线程并启动对每个组的控制?
线程进程:
public void run()
{
while (workRemaining())
{
doWork();
}
this.manager.workCompleted();
}
并在线程管理器中:
void workCompleted()
{
if (--this.runningThreads <= 0)
{
spawnNewGroup();
}
}
void spawnNewGroup()
{
for (int i=0; i<groupSize; i++)
{
startIndividualThread();
this.runningThreads++;
}
}