I have the following service code where I launch a thread responsible for dispatching messages are they come in.
public void run() {
while (! Thread.interrupted()) {
try {
Message msg = null;
synchronized (_queue) {
if (_queue.size() == 0) {
_queue.wait(10000);
}
if (_queue.size() != 0) {
msg = _queue.poll();
}
if (msg != null) {
_dispatcher.dispatch(msg);
}
}
}
catch (InterruptedException i) { }
catch (Exception e) { }
}
}
public void add (final Message m){
if (m == null)
return;
synchronized (_queue){
_queue.add(m);
_queue.notify();
}
}
But when this code runs on my android simulator, I get a lot of warnings like the following:
Long monitor contention event with owner method=void com.foo.PrioritizedMessageQueue.run() from PrioritizedMessageQueue.java:58 waiters=0 for 585ms
To me, this seems like the most efficient way of writing a queue processor. When there are not message to process, the processing thread will wait until one is added, and the "add" will notify any waiting thread why a new message is added to the queue. My thought is the dispatching thread won't use minimal resources when no message exists (as it is blocked).
However, there is a reason why android is issuing this warning but I wonder why. It is clearly not happy with my thread being blocked this long but why is that an issue? Isn't this more efficient in that it won't use any CPU cycles while it's waiting?
Also, should I be worried that android may kill my thread because it's been blocked too long? I would hate for my thread to be killed but not the service. If my service is killed, I can handle that, but I can't handle just that one thread being killed.
You should release the lock on the queue before calling _dispatcher.dispatch
. Otherwise, the outside thread attempting to call _queue.add
is blocked while the worker thread is processing the message.
Adjusting the curly braces is all that's needed. Here's your run
thread function adjusted to allow for dispatch
to be called after relinquishing the monitor of _queue
.
public void run() {
while (! Thread.interrupted()) {
try {
Message msg = null;
synchronized (_queue) { // acquire the queue lock
if (_queue.size() == 0) {
_queue.wait(10000);
}
if (_queue.size() != 0) {
msg = _queue.poll();
}
} // release the queue lock
if (msg != null) {
_dispatcher.dispatch(msg);
}
}
catch (InterruptedException i) {
}
catch (Exception e) {
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With