2013-06-25 3 views
0

У меня сценарий: Несколько событий происходят из источника, с разными типами. Мне нужно что-то делать с каждым событием того же типа в последовательности и параллельно, если это другой тип. Значение:Темы не просыпались с уведомлением

События от источника: A1, A2, B1, A3, B2, C1

  • слушателю, должны стоять в очереди A1, A2 и A3, и работать с ними в этом порядке, в один поток
  • Слушатель B так же, как а, параллельно, в другом потоке
  • Слушатель C такой же, как B, параллельно, в другом потоке

Что я делаю, чтобы достичь т его? в общих чертах, у меня есть монитор для каждого типа событий, который я инициализирую с помощью нового потока, а затем вызываю wait(). Каждый монитор имеет очередь.

Monitor.java (реализует Runnable)

public void run(){ 
    while(!killed){ 
    synchronize(this){  
     while(this.stopped){ 
     wait(); //it waits here when initialized, waiting for the first event 
     } 

     while(eventQueue.size() > 0){ 
     //do something with the event 
     } 

     //i set the flag stopped = true again to wait for the next event 
     this.stopped = true; 
    } 
    } 
} 

Когда приходит событие, я добавить его в очередь, уведомив() монитор так, чтобы он ломает время

public void awake(Event event){ 
    synchronize(this){ 
    eventQueue.add(event); 
    this.stopped = false; 
    notify(); 
    } 
} 

Флаг «убитый» используется для поддержания потока в живых до тех пор, пока не будут выполнены определенные критерии. Затем я устанавливаю убитый флаг в true и уведомляю монитор о завершении потока.

Моя проблема в том, что я запускаю множество событий, иногда поток не пробуждается с уведомлением(). Иногда обрабатывается 10 из 10 событий, иногда это 8 из 10 и так далее.

Я просматривал параллельную api, ища какую-то альтернативу для моей проблемы, но я не могу найти ничего хорошего. Не могли бы вы, ребята, дать мне совет о том, как противостоять этой проблеме?

Надеюсь, я хорошо объясню свою проблему. Если нет, спрашивайте.

Заранее спасибо.

+0

FYI: 'this.stopped' должен быть' volatile', потому что он используется несколькими потоками. – Gray

+0

'notify()' или 'notifyAll()'? – Raedwald

ответ

5

Флаг «убитый» используется для поддержания потока в живом состоянии до тех пор, пока не будут выполнены определенные критерии. Затем я устанавливаю убитый флаг в true и уведомляю монитор о завершении потока.

Во-первых, я бы серьезно рассмотреть вопрос о переходе код, чтобы использовать BlockingQueue такие как LinkedBlockingQueue. Вы все еще можете использовать флаг killed (который должен быть voltile), но с помощью BlockingQueue вся сигнализация обрабатывается для вас. Все, что вы делаете, - это позвонить put(), чтобы добавить вещи в очередь и take(), чтобы прочитать их. Вам тогда не нужно использовать synchronized, wait, или notify. Вам не нужен флаг stopped. Смотри ниже.

while (!killed) { 
    Event event = eventQueue.take(); 
    ... 

Моя проблема, когда я запускаю набор событий, иногда нить не будит с Notify(). Иногда обрабатывается 10 из 10 событий, иногда это 8 из 10 и так далее.

С точки зрения того, что происходит с вашим текущим кодом, я не вижу никаких проблем, но дьявол находится в деталях. Следует помнить, что если поток A вызывает notify() и , то поток B вызывает wait(), уведомление было потеряно. Я думаю, что вы хотите сделать что-то вроде следующего:

while(!killed){ 
    Event event; 
    synchronized (this) { 
     // wait until where is something in the queue 
     while(eventQueue.isEmpty()){ 
      this.wait(); 
     } 
     event = eventQueue.get(); 
    } 
    // work with event 
    ... 

Это единственный способ, если очередь пуста, и она не нуждается в stopped логическое значение.

+0

Мне нужно что-то делать, когда я помещаю событие в очередь? (вызывать уведомление?) или просто сообщая eventQueue.put (событие), предположим, чтобы пробудить поток? – GoVeM

+0

Вам нужно «put (...)», а затем вызвать 'notify()', который будет пробуждать потребитель _if_, он ждет @GoVeM. Если вы используете 'BlockingQueue', вам не нужно делать' notify() '. – Gray

+0

Я действительно пытаюсь решить ваше решение с помощью 'BlockingQueue', но когда я помещаю это событие, поток все еще находится в состоянии ожидания. – GoVeM