日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

延时消息_Handler的消息延时是怎么实现的

發布時間:2023/12/9 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 延时消息_Handler的消息延时是怎么实现的 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 消息延時做了什么特殊處理?

  • 是發送延時,還是消息處理延時?

  • 延時的精度如何?

通常我們使用Handler的消息延時都是調用sendMessageDelayed函數實現的,其中delayMillis是需要延時的毫秒。

通過跟蹤sendMessageDelayed函數可以發現,最終是調用到了上面這個enqueueMessage方法,其中消息隊列mMessages是單鏈表數據結果。

從上面的源碼中可以看到,當前出入的消息msg時,首先判斷mMessages消息隊列中的第一個消息mMessages.prev,要是當前隊列中消息為空,或者msg立即發送,則將該消息插到消息隊列mMessages的頭部;反之,則會在一個for的死循環中遍歷消息隊列并將傳入消息msg插到單鏈表中合適的位置。事實上,消息隊列是按照消息處理的時間when,按照從近到遠的順序排列的,最先要執行的任務放在消息隊列的頭部,依次排列。

從上面可以看到,Handler中sendMessageDelayed方法只是將消息按照要執行的先后順序插入到消息隊列中的,插入好了并不意味著就會按照設定的延時時間處理消息,那Handler時如何延時處理該消息的呢?

首先我們知道,Looper.loop()之后,線程就進入了消息監聽的階段:

當Handler中沒有可用消息的時候,上面代碼會一直阻塞在queue.next()的地方,直到消息返回,才會調用dispatchMessage進行消息的處理,要是返回的msg為空,那么Handler就會結束消息監聽,不再監聽任何消息。

我們來看看queue.next()函數:

上面是阻塞的從消息隊列中獲取可用消息的過程。其中nativePollOnce方法是一個native方法,其內部會根據傳入的nextPollTimeoutMillis,在延遲這么長時間之后喚醒線程從消息隊列中讀取消息,內部調用的是epoll_wait方法。

我們知道當線程中沒有新消息要處理的時候,線程處于休眠狀態,當其他線程向Handler的消息隊列中寫入消息,這一動作并不會喚醒當前線程處理該消息,還需要向線程的eventfd中寫入數據,從而喚醒休眠的線程開始處理數據,此處也是一樣的,nativePollOnce函數內部會調用epoll_wait方法,設置超時時間為nextPollTimeoutMillis,epoll_wait在這個超時時間之后,就會喚醒線程,開始處理消息隊列中的消息。

next方法中,每次會從消息隊列mMessages中獲取鏈表中頭部的消息,要是頭部消息的設定執行的時間要比當前時間大,說明消息隊列中所有的消息都還沒有到可執行的時間,這是因為消息隊列中消息在插入消息隊列的時候,按照執行時間的先后順序已經排序好了。這種情況下,會計算出一個等待時間,傳遞到nativePollOnce函數中,讓native層在這個等待時間之后再喚醒線程讀取消息隊列中的消息,進行消息處理。

Handler的消息延時的實現:

消息隊列在插入消息的時候是按照消息的觸發時間順序排序的,先執行的消息放在單鏈表的頭部,最后執行的消息放在單鏈表的尾部;

在消息執行的過程中,通過native層設置epoll_wait的超時事件,使其在特定時間喚醒線程開始出現消息。

關于延時精度:Handler的延時精度并不高,會受到前一個消息處理時間的影響,因為在Looper.loop()方法中,只有上一個消息被處理完之后,才會去queue中讀取下一個消息。

?

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的延时消息_Handler的消息延时是怎么实现的的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。