<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                #### 10.2.2 消息隊列的工作原理 消息隊列在Android中指的是[MessageQueue](https://www.androidos.net.cn/android/6.0.1_r16/xref/frameworks/base/core/java/android/os/MessageQueue.java), MessageQueue主要包含兩個操作:**插入和讀取**。 **讀取操作本身會伴隨著刪除操作**,**插入和讀取**對應的方法分別為**enqueueMessage和next**,其中 * **enqueueMessage**的作用是**往消息隊列中插入一條消息**, * 而**next的作用是從消息隊列中取出一條消息并將其從消息隊列中移除**。 盡管MessageQueue叫消息隊列,但是**它的內部實現并不是用的隊列**,實際上它是通過**一個單鏈表的數據結構來維護消息列表,單鏈表在插入和刪除上比較有優勢**。 MessageQueue是消息機制的Java層和C++層的連接紐帶,大部分核心方法都交給native層來處理,其中MessageQueue類中涉及的native方法如下: ``` private native static long nativeInit(); private native static void nativeDestroy(long ptr); private native void nativePollOnce(long ptr, int timeoutMillis); private native static void nativeWake(long ptr); private native static boolean nativeIsPolling(long ptr); private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events); ``` 下面主要看一下它的enqueueMessage和next方法的實現,enqueueMessage的源碼如下所示。 ``` boolean enqueueMessage(Message msg, long when) { // 每一個普通Message必須有一個target if (msg.target == null) { throw new IllegalArgumentException("Message must have a target."); } if (msg.isInUse()) { throw new IllegalStateException(msg + " This message is already in use."); } synchronized (this) { if (mQuitting) { //正在退出時,回收msg,加入到消息池 msg.recycle(); return false; } msg.markInUse(); msg.when = when; Message p = mMessages; boolean needWake; if (p == null || when == 0 || when < p.when) { //p為null(代表MessageQueue沒有消息) 或者msg的觸發時間是隊列中最早的, 則進入該該分支 msg.next = p; mMessages = msg; needWake = mBlocked; //當阻塞時需要喚醒 } else { //將消息按時間順序插入到MessageQueue。一般地,不需要喚醒事件隊列,除非 //消息隊頭存在barrier,并且同時Message是隊列中最早的異步消息。 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; } } msg.next = p; prev.next = msg; } //消息沒有退出,我們認為此時mPtr != 0 if (needWake) { nativeWake(mPtr); } } return true; } ``` 從**enqueueMessage**的實現來看,它的**主要操作其實就是單鏈表的插入操作**,這里就不再過多解釋了, 下面看一下next方法的實現,next的主要邏輯如下所示。 ``` Message next() { final long ptr = mPtr; if (ptr == 0) { //當消息循環已經退出,則直接返回 return null; } int pendingIdleHandlerCount = -1; // 循環迭代的首次為-1 int nextPollTimeoutMillis = 0; for (;;) { if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); } //阻塞操作,當等待nextPollTimeoutMillis時長,或者消息隊列被喚醒,都會返回 nativePollOnce(ptr, nextPollTimeoutMillis); synchronized (this) { final long now = SystemClock.uptimeMillis(); Message prevMsg = null; Message msg = mMessages; //當消息的Handler為空時,則查詢異步消息 if (msg != null && msg.target == null) { //當查詢到異步消息,則立刻退出循環 do { prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous()); } if (msg != null) { if (now < msg.when) { //當異步消息觸發時間大于當前時間,則設置下一次輪詢的超時時長 nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); } else { // 獲取一條消息,并返回 mBlocked = false; if (prevMsg != null) { prevMsg.next = msg.next; } else { mMessages = msg.next; } msg.next = null; //設置消息的使用狀態,即flags |= FLAG_IN_USE msg.markInUse(); return msg; //成功地獲取MessageQueue中的下一條即將要執行的消息 } } else { //沒有消息 nextPollTimeoutMillis = -1; } //消息正在退出,返回null if (mQuitting) { dispose(); return null; } //當消息隊列為空,或者是消息隊列的第一個消息時 if (pendingIdleHandlerCount < 0 && (mMessages == null || now < mMessages.when)) { pendingIdleHandlerCount = mIdleHandlers.size(); } if (pendingIdleHandlerCount <= 0) { //沒有idle handlers 需要運行,則循環并等待。 mBlocked = true; continue; } if (mPendingIdleHandlers == null) { mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)]; } mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers); } //只有第一次循環時,會運行idle handlers,執行完成后,重置pendingIdleHandlerCount為0. for (int i = 0; i < pendingIdleHandlerCount; i++) { final IdleHandler idler = mPendingIdleHandlers[i]; mPendingIdleHandlers[i] = null; //去掉handler的引用 boolean keep = false; try { keep = idler.queueIdle(); //idle時執行的方法 } catch (Throwable t) { Log.wtf(TAG, "IdleHandler threw exception", t); } if (!keep) { synchronized (this) { mIdleHandlers.remove(idler); } } } //重置idle handler個數為0,以保證不會再次重復運行 pendingIdleHandlerCount = 0; //當調用一個空閑handler時,一個新message能夠被分發,因此無需等待可以直接查詢pending message. nextPollTimeoutMillis = 0; } } ``` 可以發現**next方法是一個無限循環的方法,如果消息隊列中沒有消息,那么next方法會一直阻塞在這里**。 當**有新消息到來時,next方法會返回這條消息并將其從單鏈表中移除**。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看