Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 执行线程";“一个接一个”;_Java_Multithreading_Thread Safety - Fatal编程技术网

Java 执行线程";“一个接一个”;

Java 执行线程";“一个接一个”;,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,有n个线程可以访问的单例类。 每个线程加载该类的实例,并在循环中从该类调用一个方法 我必须控制执行流,这样每个线程都可以调用方法1并暂停,只有在所有线程调用方法后,线程才能恢复工作。 线程可以按任何顺序调用方法,只是所有线程在移动循环之前都必须执行一次方法 这就是我试图做的: 在线程中: while ( some condition){ ObjectType obj = theSingleton.getInstance().getSharedObject(); obj.Some

有n个线程可以访问的单例类。
每个线程加载该类的实例,并在循环中从该类调用一个方法

我必须控制执行流,这样每个线程都可以调用方法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();