(一)MessageQueue之消息入队

时间:2022-07-23
本文章向大家介绍(一)MessageQueue之消息入队,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
java 尾插法插入单链表

每来一个新节点,插入到链表的最后

先用伪代码整理一下思路,如下:

public class SimpleNode {
   // 当前链表,
   Node mNode;

   public void insert(Node node) {
       // 1.链表为null,第一次插入
       if (mNode == null) {
           //node作为第一个元素,放入mNode
      } else {
          //2.1 链表不为null,找出最后一个节点
          //2.2 将待插入节点 Node 插入 最后一个节点之后  
      }
  }
   
   //节点
   public class Node {
       int data;
       Node next;

       public Node() {
           this.next = null;
      }
  }    
}

因此我们的代码可以这么写:

public class SimpleNode {
   // 当前链表
   Node mNode;

   public class Node {
       int data;
       Node next;

       public Node() {
           this.next = null;
      }
  }

   public void insert(Node node) {
       //创建一个临时节点
       Node currentNode = mNode;
       // 1.链表为null,第一次插入
       if (currentNode == null) {
           mNode = node;
      } else {
           // 2.1 遍历链表,找出最后一个节点
           Node realLastNode;
           for (; ; ) {
               realLastNode = currentNode;
               currentNode = currentNode.next;
               //在 for 循环中,如果此时currentNode为 null,说明链表没有节点了,即realLastNode.next为 null,
               //realLastNode就是我们要找的节点,退出 for 循环
               if (currentNode == null) {
                   break;
              }
          }
           //将待插入节点 Node 插入到最后    
           realLastNode.next = node;
      }
  }

}
MessageQueue 中的 msg 入队

有了上面的知识,我们看一下MessageQueue 是怎么将 msg 入队的?

按照我个人的理解,有如下几点:

  1. 在MessageQueue中msg按照时间顺序进入消息队列
  2. 延迟越大的消息,越在队列的后面

假设发送消息的时间单位为秒

假设消息只入队,不消费.

比如我们在 16:10:40s 入队一个消息 A,41s入队的消息 B,42s 入队消息C

则 BC都在 A 的后面,

因此在MessageQueue中 msg按时间顺序排队

顺序是 ABC

源码分析
public final class MessageQueue {
   
   
   boolean enqueueMessage(Message msg, long when) {
       //...
       //同步方法块
       synchronized (this) {
           //...
           msg.when = when;
           Message p = mMessages;
           boolean needWake;
           //1.1 当前mMessages 为 null,队列中没有消息
           //1.2 当前mMessages 不为 null,when == 0说明队列中的消息都是延迟的消息
           //1.3 当前mMessages 不为 null,when < p.when 说明当前消息是延迟消息,但是队列中的消息比我这个消息延迟还大.
           if (p == null || when == 0 || when < p.when) {
               // New head, wake up the event queue if blocked.
               //将当前消息作为mMessages的第一个
               //此时 p 是 null
               msg.next = p;
               //更新mMessages
               mMessages = msg;
               needWake = mBlocked;
          } else {
               needWake = mBlocked && p.target == null && msg.isAsynchronous();
               //这儿的逻辑就是上面的尾插了...
               Message prev;
               for (;;) {
                   prev = p;
                   p = p.next;
                   if (p == null || when < p.when) {
                       break;
                  }
                   if (needWake && p.isAsynchronous()) {
                       needWake = false;
                  }
              }
               //此时 p 是 null
               msg.next = p; // invariant: p == prev.next
               prev.next = msg;
          }

           // We can assume mPtr != 0 because mQuitting is false.
           if (needWake) {
               nativeWake(mPtr);
          }
      }
       return true;
  }    
   
}

代码中的注释,就是消息入队的过程

更多内容 欢迎关注公众号