自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Android中消息隊(duì)列延時(shí)不準(zhǔn)確的原因,從系統(tǒng)時(shí)鐘的精度到MessageQueue的機(jī)制

移動(dòng)開(kāi)發(fā) Android
從系統(tǒng)時(shí)鐘看已經(jīng)過(guò)去1個(gè)小時(shí)了,但是計(jì)算now時(shí)因?yàn)閡ptimeMillis不包含休眠時(shí)的時(shí)間。如果now < msg.when 會(huì)判定Messsage還沒(méi)有到執(zhí)行時(shí)間,就不會(huì)從MessageQueue中取出并執(zhí)行。

SystemClock系統(tǒng)時(shí)鐘

SystemClock類是一個(gè)用于獲取時(shí)間信息的核心類,為Android開(kāi)發(fā)者提供了多種與時(shí)間相關(guān)的功能。

  1. 「類聲明和結(jié)構(gòu)」:

SystemClock是一個(gè)final類,繼承自O(shè)bject,不能被繼承。

不可變類,提供了與時(shí)間相關(guān)的多種方法。

  1. 「主要方法」:

SystemClock.uptimeMillis():

返回從系統(tǒng)啟動(dòng)開(kāi)始到現(xiàn)在的非休眠時(shí)間的毫秒數(shù)。

當(dāng)系統(tǒng)進(jìn)入深度睡眠(CPU休眠、屏幕休眠、設(shè)備等待外部輸入)時(shí),該時(shí)間停止。

SystemClock.elapsedRealtime() 和 SystemClock.elapsedRealtimeNanos():

返回從系統(tǒng)啟動(dòng)到現(xiàn)在的總時(shí)間,包括深度睡眠的時(shí)間。

兩個(gè)方法返回的時(shí)間都是單調(diào)的,即使在省電模式下也會(huì)繼續(xù)計(jì)時(shí)。

SystemClock.sleep(long):

類似于Thread.sleep(long),忽略了InterruptedException異常。

SystemClock.setCurrentTimeMillis(long):

「注意」:通常用于設(shè)置系統(tǒng)時(shí)間,需要系統(tǒng)權(quán)限。

將系統(tǒng)時(shí)間設(shè)置為指定的毫秒數(shù),通常只在系統(tǒng)源碼環(huán)境下使用,并且需要特定的編譯和簽名過(guò)程。

  1. 「其他注意事項(xiàng)」:

監(jiān)聽(tīng)時(shí)間變化:

通過(guò)監(jiān)聽(tīng)ACTION_TIME_TICK、ACTION_TIME_CHANGED和ACTION_TIMEZONE_CHANGED等廣播,可以獲取系統(tǒng)時(shí)間是否發(fā)生改變。

  1. 「權(quán)限要求」:

修改系統(tǒng)時(shí)間(如使用SystemClock.setCurrentTimeMillis(long))需要系統(tǒng)權(quán)限,應(yīng)用需要在Android系統(tǒng)源碼環(huán)境下進(jìn)行編譯和簽名。

Hander延時(shí)消息延時(shí)會(huì)不準(zhǔn)確

Hanler中發(fā)送消息(或者延時(shí)消息) 是通過(guò)SystemClock.uptimeMillis()為基準(zhǔn)計(jì)算。

MessageQueue入隊(duì)列時(shí),計(jì)算Message.when以SystemClock.uptimeMillis()時(shí)間為基準(zhǔn)。

public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

從MessageQueue中消費(fèi)Message,判斷Message是否到了執(zhí)行時(shí)間,也是以SystemClock.uptimeMillis()為基準(zhǔn)。

//Looper.loop()循環(huán)
public static void loop() {
    for (;;) {
        Message msg = queue.next(); // might block
        msg.target.dispatchMessage(msg);
    }
}

//MessageQueue類的next方法
//msg.when > now時(shí) 才會(huì)將Message取出然后執(zhí)行。
Message next() {
    for (;;) {
        ...
        synchronized (this) {
            // (1)計(jì)算當(dāng)前時(shí)間
            final long now = SystemClock.uptimeMillis();
        
            // 返回取到的Message 
            if (msg != null) {
                //msg尚未到達(dá)觸發(fā)時(shí)間,則計(jì)算新的阻塞超時(shí)時(shí)間nextPollTimeoutMillis,下次循環(huán)觸發(fā)隊(duì)列阻塞
                if (now < msg.when) {
                    // Next message is not ready.  Set a timeout to wake up when it is ready.
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {
                    //從鏈表中移除該消息后,直接返回
                    // Got a message.
                    mBlocked = false;
                    if (prevMsg != null) {
                        prevMsg.next = msg.next;
                    } else {
                        mMessages = msg.next;
                    }
                    msg.next = null;
                    msg.markInUse();
                    return msg;
                }
            } 
            ...
    }
}

SystemClock.uptimeMillis()計(jì)算系統(tǒng)從開(kāi)機(jī)到現(xiàn)在的時(shí)間,單位是毫秒。但是它不包括系統(tǒng)休眠的時(shí)間(cpu休眠、屏幕休眠等)。

當(dāng)手機(jī)滅屏處于休眠狀態(tài)的時(shí)間是不計(jì)算進(jìn)SystemClock.uptimeMillis(),比如發(fā)送一個(gè)延時(shí)20分鐘的Message消息,系統(tǒng)息屏后進(jìn)入了深度睡眠(假設(shè)深度睡眠了1個(gè)小時(shí)),當(dāng)進(jìn)程蘇醒后,這一個(gè)小時(shí)的時(shí)間是不計(jì)入(1)中的now。

final long now = SystemClock.uptimeMillis();

從系統(tǒng)時(shí)鐘看已經(jīng)過(guò)去1個(gè)小時(shí)了,但是計(jì)算now時(shí)因?yàn)閡ptimeMillis不包含休眠時(shí)的時(shí)間。如果now < msg.when 會(huì)判定Messsage還沒(méi)有到執(zhí)行時(shí)間,就不會(huì)從MessageQueue中取出并執(zhí)行。

責(zé)任編輯:武曉燕 來(lái)源: 沐雨花飛蝶
相關(guān)推薦

2010-03-26 14:43:09

CentOS系統(tǒng)

2009-10-12 13:57:35

VMware虛擬機(jī)時(shí)鐘

2024-10-16 15:11:58

消息隊(duì)列系統(tǒng)設(shè)計(jì)

2020-09-27 07:44:08

RabbitMQ投遞消息

2021-03-11 06:01:41

Linux消息隊(duì)列

2009-08-06 16:17:05

點(diǎn)對(duì)點(diǎn)消息隊(duì)列

2023-11-07 10:01:34

2013-04-11 12:40:16

Android消息機(jī)制

2021-05-07 22:17:06

手機(jī)定位信號(hào)

2011-12-02 10:58:06

數(shù)據(jù)結(jié)構(gòu)Java

2011-05-31 11:55:00

Android 消息機(jī)制

2017-05-15 19:40:40

AndroidIPC機(jī)制

2013-03-28 09:07:37

Android開(kāi)發(fā)Intent機(jī)制

2019-10-22 08:12:49

消息隊(duì)列分布式系統(tǒng)

2022-06-13 11:05:35

RocketMQ消費(fèi)者線程

2021-12-06 23:00:36

CC++編程語(yǔ)言

2014-03-04 15:28:32

iOS開(kāi)發(fā)消息傳遞機(jī)制

2021-11-24 08:33:09

Android廣播機(jī)制應(yīng)用程序

2011-06-03 08:58:14

2010-04-21 14:49:13

Unix消息隊(duì)列
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)