Reputation: 5
I have the following scenario: Multiple events are coming from a source, with different types each. I need to do something with each event of the same type in sequence, and in parallel if other type. Meaning:
Events from source: A1, A2, B1, A3, B2, C1
What am i doing to achieve this? in general terms, i have a monitor for each type of event which i initialize with a new thread and then call to wait(). Every monitor has a queue.
Monitor.java (implements 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;
}
}
}
When an event arrives, i add it to the queue then notify() the monitor so it breaks the while
public void awake(Event event){
synchronize(this){
eventQueue.add(event);
this.stopped = false;
notify();
}
}
The "killed" flag is used to maintain the thread alive until certain criteria is met. Then, i set the killed flag on true and notify the monitor to end the thread.
My problem is when i run a set of events, sometimes the thread does not awake with the notify(). Sometimes 10 out of 10 events are processed, sometimes, it's 8 of 10 and so on.
I've been looking through the concurrent api searching for some alternative for my problem but i can't find anything good. Could you guys give me any advice on how to confront this problem?
i hope i'm explaining my problem in a good way. If not, please ask.
Thanks in advance.
Upvotes: 0
Views: 172
Reputation: 116908
The "killed" flag is used to maintain the thread alive until certain criteria is met. Then, i set the killed flag on true and notify the monitor to end the thread.
First off, I would seriously consider switching your code to use a BlockingQueue
such as the LinkedBlockingQueue
. You can still use the killed
flag (which must be voltile
btw), but by using the BlockingQueue
all of the signaling is handled for you. All you do is call put()
to add things to the queue and take()
to read from it. You then don't need to use synchronized
, wait
, or notify
. You don't need the stopped
flag at all. See below.
while (!killed) {
Event event = eventQueue.take();
...
My problem is when i run a set of events, sometimes the thread does not awake with the notify(). Sometimes 10 out of 10 events are processed, sometimes, it's 8 of 10 and so on.
In terms of what is going wrong with your current code, I don't see any problems but the devil is in the details. One thing to remember is that if thread A calls notify()
and then thread B calls wait()
the notify has been lost. I think you want to do something like the following:
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
...
This will only way if the queue is empty and it does not need the stopped
boolean.
Upvotes: 5