我有以下服务代码,我在其中启动了一个负责调度消息的线程。
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();
}
}
但是当这个代码在我的android模拟器上运行时,我收到了很多警告,如下所示:
Long monitor contention event with owner method=void com.foo.PrioritizedMessageQueue.run() from PrioritizedMessageQueue.java:58 waiters=0 for 585ms
对我而言,这似乎是编写队列处理器的最有效方式。当没有要处理的消息时,处理线程将等待,直到添加一个消息,并且"添加"将通知任何等待的线程为什么将新消息添加到队列中。我的想法是当没有消息存在时(因为它被阻止),调度线程不会使用最少的资源。
然而,有一个原因是android发出这个警告,但我想知道为什么。很明显我的线程被阻止了很长时间,但为什么这是一个问题呢?这不是更高效,因为它在等待时不会使用任何CPU周期吗?
另外,我是否应该担心android可能会因为被阻止太久而杀死我的帖子?我讨厌我的线程被杀,但不是服务。如果我的服务被杀了,我可以处理,但我无法处理被杀死的一个线程。
答案 0 :(得分:2)
在调用_dispatcher.dispatch
之前,您应该释放队列上的锁。否则,当工作线程正在处理消息时,阻止尝试调用_queue.add
的外部线程。
只需调整花括号即可。这里调整了run
线程函数,以便在放弃dispatch
的监视器后调用_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) {
}
}
}