Java 执行线程";“一个接一个”;
有n个线程可以访问的单例类。Java 执行线程";“一个接一个”;,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,有n个线程可以访问的单例类。 每个线程加载该类的实例,并在循环中从该类调用一个方法 我必须控制执行流,这样每个线程都可以调用方法1并暂停,只有在所有线程调用方法后,线程才能恢复工作。 线程可以按任何顺序调用方法,只是所有线程在移动循环之前都必须执行一次方法 这就是我试图做的: 在线程中: while ( some condition){ ObjectType obj = theSingleton.getInstance().getSharedObject(); obj.Some
每个线程加载该类的实例,并在循环中从该类调用一个方法 我必须控制执行流,这样每个线程都可以调用方法1并暂停,只有在所有线程调用方法后,线程才能恢复工作。 线程可以按任何顺序调用方法,只是所有线程在移动循环之前都必须执行一次方法 这就是我试图做的: 在线程中:
while ( some condition){
ObjectType obj = theSingleton.getInstance().getSharedObject();
obj.SomeMethod(threadID);
if (obj.waitisneeded())
synchronized (obj ) {
obj.wait();
}
}
我用某种方法做了什么:
public synchronized void SomeMethod(String threadID) {
hashMap.put(threadID,true);
some job here
}
在等待中需要:
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循环)如果您知道线程数,可以使用: 然后,在要使所有线程等待其他线程的时刻,调用:
barrier.await();
如果有一个线程尚未到达该行,那么调用await()
的线程将被阻塞。一旦所有线程到达那里并调用await()
,它们将全部恢复
每次必须构建一些同步机制时,请确保检查包。那里有很多精彩的课程,都是由专家们创造的。大多数情况下,您不需要定制一些东西,如果您需要定制,那么同一个包中的一些类几乎不需要直接使用wait/notify——而且,相信我,您希望避免直接使用这些方法;正如你所看到的,你很容易陷入僵局 这是一种典型的多线程情况,称为Rendez-Vous(法语单词,意思是“约会”)。基本上,您的
N
线程将有一个约会,所有线程都应该在某个时间点等待,直到所有线程都到达该时间点。正如@Bruno所提到的,您可以使用CyclicBarrier
对象来管理这种情况。如果您的场景只运行一次,那么您也可以使用倒计时闩锁
以下是实现此目标的方法:
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)您知道在每个线程调用obj.SomeMethod()
之前创建了多少个线程吗?您如何知道“所有预期的线程现在都已调用singleton“联系到了吗?@thecrummeister Scrum Meister是的,我知道threads@Thorbjørn Ravn Andersen,正如您在代码中看到的,getSharedObject中有一个hashmap,我在其中标记访问它的线程。检查所有线程后,我想释放线程并清除hashmap,以便它们可以重新开始。我不确定我是否喜欢使用CountDownLatch
。您正在破坏一个倒计时闩锁
,使它的行为完全像一个循环载波
(它是为处理这种情况而构建的)。方法CDL.countDown()
和CDL.await()
,按您所做的方式调用,它们的行为大部分类似于CB.await()
,但它们是两种方法(不是一个接一个地调用):通常,工作线程将调用CDL.countDown()
,只有主线程将调用CDL.await()
,为了阻止,直到所有工作线程完成任务为止。@Brunores谢谢你的评论,我倾向于不同意你的观点。根据java官方文档,依次执行CDL.countDown()
和CDL.await()
并没有错。CyclicBarrier
(根据文档)是可重复使用的(可以多次设置和重置)版本的CountDownLatch
我认为CyclicBarrier存在问题,因为var是静态的。在我的应用程序中,这种情况可以并行发生多次!X线程(我忘了提到),getSharedObject被生成并存储在singleton的hashmap变量中。因此,每组线程都访问自己的对象。这就是为什么我尝试使用lock,并使用getSharedObject自身作为锁!如果我使用static,我必须为每个getSharedObjectWell创建新变量,我不知道应用程序是如何工作的。我相信你能适应你的场景!整个想法是,在恢复之前必须互相等待的线程必须共享一个CyclicBarrier。但一定要正确地发布障碍!(也就是说,由于您将有许多cyclicBarrier,因此最好使用并发集合来保存实例,例如ConcurrentHashMap)。
static final CountDownLatch rendezVousPoint = new CountDownLacth(numberOfThreads);
//Every thread does the following right before waiting on the rendez vous point
rendezVousPoint.countDown();
rendezVousPoint.await();