n个线程可以访问一个单例类 每个线程加载此类的实例,并在循环中从此类调用方法。
我必须控制执行流程,这样每个线程都可以调用方法一并暂停,只有在必须恢复工作后所有线程调用该方法之后。 线程可以按任何顺序调用方法,只需要在移动循环之前执行方法一次。
这就是我试图做的事情:
在线程中:
while ( some condition){
ObjectType obj = theSingleton.getInstance().getSharedObject();
obj.SomeMethod(threadID);
if (obj.waitisneeded())
synchronized (obj ) {
obj.wait();
}
}
我在SomeMethod中做了什么:
public synchronized void SomeMethod(String threadID) {
hashMap.put(threadID,true);
some job here
}
并且在waitisneeded中:
public synchronized boolean waitisneeded(){
{
Iterator iter = hashMap.entrySet().iterator();
boolean alldone = false;
while (iter.hasNext()) {
Map.Entry me = (Map.Entry) iter.next();
String key = me.getKey().toString();
alldone = (Boolean)me.getValue();
if(!alldone) {
return false;
}
}
//set all values to false
iter = hashMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry me = (Map.Entry) iter.next();
String key = me.getKey().toString();
me.setValue(false);
}
this.notifyAll();
return true;
运行它会让我意想不到的结果和死锁。
我该如何解决?
注意:我无法改变线程的创建方式,我只能改变那些方法! (加上等待的线程中的while循环)
答案 0 :(得分:2)
如果您知道线程数,可以使用CyclicBarrier
:
static final CyclicBarrier barrier = new CyclicBarrier(numberOfThreads);
然后,在您想让所有线程等待其他线程的时刻,您可以调用:
barrier.await();
如果有一个尚未到达该行的线程,则调用await()
的线程将被阻止。一旦所有线程到达并呼叫await()
,它们都将恢复。
每次必须构建一些同步机制时,请务必检查包java.util.concurrent。那里有很多精彩的课程,由专家创建。大多数时候你不需要自定义的东西,如果你这样做,在同一个包中有一些类几乎不需要直接使用wait / notify - 而且,相信我,你想要避免直接使用这些方法;正如你所看到的,你很容易陷入僵局!
答案 1 :(得分:0)
这是一种典型的多线程情况,称为Rendez-Vous(法语单词意为"约会")。基本上你的N
线程会有一个约会,并且应该等到一个点,直到所有线程都达到它。正如@Bruno所提到的,您可以使用CyclicBarrier
对象来管理这种情况。如果您的方案只运行一次,那么您也可以使用CountDownLatch
。
以下是如何实现这一目标:
static final CountDownLatch rendezVousPoint = new CountDownLacth(numberOfThreads);
//Every thread does the following right before waiting on the rendez vous point
rendezVousPoint.countDown();
rendezVousPoint.await();
在这种情况下,每个线程都会阻塞await()
方法,直到最后一个线程到达并释放所有线程(rendezVousPoint
计数达到0)