"Long monitor contention event" 有什么问题

What's the issue with "Long monitor contention event"

我有以下服务代码,我在其中启动负责调度消息的线程。

       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

对我来说,这似乎是编写队列处理器的最有效方式。当没有消息要处理时,处理线程将等待直到添加一个,并且 "add" 将通知任何等待线程为什么将新消息添加到队列中。我的想法是,当不存在消息时(因为它被阻塞),调度线程不会使用最少的资源。

但是,android 发出此警告是有原因的,但我想知道为什么。它显然对我的线程被阻塞这么长时间不满意,但为什么这是一个问题?这不是更有效率,因为它在等待时不会使用任何 CPU 周期吗?

此外,我是否应该担心 android 可能会因为阻塞时间过长而终止我的线程?我讨厌我的线程被杀死而不是服务。如果我的服务被终止,我可以处理,但我不能只处理一个线程被终止。

您应该在调用 _dispatcher.dispatch 之前释放队列上的锁。否则,试图调用 _queue.add 的外部线程会在工作线程处理消息时被阻塞。

只需调整花括号即可。这是调整后的 run 线程函数,允许在放弃 _queue.

的监视器后调用 dispatch
   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) {
        }
      }
  }