Выполнение потока "один за другим" - PullRequest
2 голосов
/ 19 декабря 2011

Существует одноэлементный класс, к которому могут обращаться n потоков.
Каждый поток загружает экземпляр этого класса и вызывает метод из этого класса в цикле.

Я должен контролировать поток выполнения, чтобы каждый поток мог вызвать метод one и сделать паузу, только после того, как весь поток вызвал метод, как только он должен возобновить свою работу.Потоки могут вызывать метод в любом порядке, только все они должны выполнить метод один раз перед перемещением цикла.

Это то, что я пытался сделать:

В потоке:

 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 ]

2 голосов
/ 19 декабря 2011

Если вам известно количество потоков, вы можете использовать CyclicBarrier:

static final CyclicBarrier barrier = new CyclicBarrier(numberOfThreads);

Затем в точке, в которой вы хотите, чтобы все потоки ожидалидругие, вы вызываете:

barrier.await();

Если есть поток, который еще не достиг этой строки, поток, вызывающий await(), заблокируется.Как только все потоки прибывают туда и вызывают await(), они все возобновят работу.

Каждый раз, когда вам необходимо создать какой-либо механизм синхронизации, обязательно проверяйте пакет java.util.concurrent .Там много замечательных классов, созданных экспертами.Большую часть времени вам не понадобится что-то нестандартное, и если вы это сделаете, в одном и том же пакете есть классы, которые сделают практически ненужным прямое ожидание / уведомление - и, поверьте мне, вы хотите избежать их использованияметоды напрямую;как видите, вы легко можете оказаться в тупике!

0 голосов
/ 19 декабря 2011

Это типичная многопоточная ситуация, называемая 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)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...