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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

handler 消息处理机制

發布時間:2023/11/29 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 handler 消息处理机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

關于handler消息處理機制,只要一提到,相信作為一個android工程師,腦海就會有這么一個流程

大家都滾瓜爛熟了,但別人問到幾個問題,很多人還是栽到這個“爛”上面,比如:

  • 一個線程是如何對應一個Lopper的?
  • messageQueue是如何做到線程安全的?
    首先先Looper看一段代碼:
private static void prepare(boolean quitAllowed) {if (sThreadLocal.get() != null) {throw new RuntimeException("Only one Looper may be created per thread");}sThreadLocal.set(new Looper(quitAllowed));}

這里先通過sThreadLocal.get()去獲取這個Looper, 獲取不到再去通過new (Looper(quitAllowed))去創建Looper()對象。再來看看這個構造函數:

private Looper(boolean quitAllowed) {mQueue = new MessageQueue(quitAllowed);mThread = Thread.currentThread();}

構造函數私有的,只能通過Prepare去初始化,這里就形成了一個關系,一個Looper 對應一個MessageQueue。

回過頭再來分析,線程是如何和Looper對應的。

/*** Return the Looper object associated with the current thread. Returns* null if the calling thread is not associated with a Looper.*/public static @Nullable Looper myLooper() {return sThreadLocal.get();}

在Prepare()的時候給sThreadLocal.set(Looper), 獲取Looper的對象是通過sThreadLocal.get()返回的,下面看看sThreadLocal:

// sThreadLocal.get() will return null unless you've called prepare().static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

這是一個靜態成員變量所有的Looper對象共有屬性。
sTreadLocal保存線程的唯一值,這樣就保證一個線程對應一個looper.

至于MessageQueue的線程同步,會有奇葩的人問到,無非就是syncnized關鍵字,或者加鎖。

boolean enqueueMessage(Message msg, long when) {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) {IllegalStateException e = new IllegalStateException(msg.target + " sending message to a Handler on a dead thread");Log.w(TAG, e.getMessage(), e);msg.recycle();return false;}msg.markInUse();msg.when = when;Message p = mMessages;boolean needWake;if (p == null || when == 0 || when < p.when) {// New head, wake up the event queue if blocked.msg.next = p;mMessages = msg;needWake = mBlocked;} else {// Inserted within the middle of the queue. Usually we don't have to wake// up the event queue unless there is a barrier at the head of the queue// and the message is the earliest asynchronous message in the queue.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; // invariant: p == prev.nextprev.next = msg;}// We can assume mPtr != 0 because mQuitting is false.if (needWake) {nativeWake(mPtr);}}return true;}

這里用的是一個加鎖的方式。
在Loop.loop中有一死循環,那么當沒有消息時,主線程不可能死掉吧?
“`
在主線程的MessageQueue沒有消息時,便阻塞在loop的queue.next()中的nativePollOnce()方法里,此時主線程會釋放CPU資源進入休眠狀態,直到下個消息到達或者有事務發生,通過往pipe管道寫端寫入數據來喚醒主線程工作。這里采用的epoll機制,是一種IO多路復用機制,可以同時監控多個描述符,當某個描述符就緒(讀或寫就緒),則立刻通知相應程序進行讀或寫操作,本質同步I/O,即讀寫是阻塞的。 所以說,主線程大多數時候都是處于休眠狀態,并不會消耗大量CPU資源。

還有什么關于handler的問題,希望大家可以提出來。

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

總結

以上是生活随笔為你收集整理的handler 消息处理机制的全部內容,希望文章能夠幫你解決所遇到的問題。

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