执行线程“一个接一个”

时间:2011-12-18 22:17:53

标签: java multithreading thread-safety

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循环)

2 个答案:

答案 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)