Handler 40問

1,handler 機(jī)制中甥啄,存在哪些角色?各自承擔(dān)了什么功能融虽?

1.Handler :消息輔助類& 對(duì)外的接口& 向MQ投遞消息&消息的目標(biāo)處理者
2.Message :消息的載體&被Handler投遞&自帶Handler處理&自帶處理池
3.Looper :循環(huán)器&持有MQ&循環(huán)從MQ中獲取消息&TLS線程唯一
4.MessageQueue:基于時(shí)間的優(yōu)先級(jí)隊(duì)列&鏈表結(jié)構(gòu)&java與C++層的紐帶
[圖片上傳失敗...(image-25c28e-1616424380917)]

2.Handler機(jī)制中,Message和Runnable的區(qū)別彼绷?

1.本質(zhì)上沒有區(qū)別的萤衰,MQ只接受Message倦卖,Runnable 會(huì)被轉(zhuǎn)換成Message入隊(duì)

2.Runnable 通過getPostMessage()方法轉(zhuǎn)換成Message對(duì)象

3.Runnable 轉(zhuǎn)換的Message怕膛,Runnable 會(huì)被記錄在MSG的callback屬性上,在處理消息時(shí)柠逞,優(yōu)先被處理

3.Handler分發(fā)事件優(yōu)先級(jí)陵且,是否可以攔截聊疲?攔截的優(yōu)先級(jí)如何?

1.Handler中贡珊,通過dispatchMessage()處理消息,其中存在優(yōu)先級(jí)策略

2.優(yōu)先級(jí)1:msg.callback 寒随,run -獨(dú)占

3.優(yōu)先級(jí)2:mCallback.handlerMessage(msg) -返回值決定是非法攔截該消息

mCallback 屬于 Handler妻往,是消息的統(tǒng)?攔截機(jī)制。

3.優(yōu)先級(jí)3:handle.handleMessage()


image

4.Handler 在處理 Message 的時(shí)候局嘁,可以對(duì)消息統(tǒng)?攔截嗎悦昵?如何做?有什么缺點(diǎn)棋凳?

1.可以

2.實(shí)現(xiàn):使用Handler的Callback;通過Handler的構(gòu)造方法傳遞Callback對(duì)象拍棕,并實(shí)現(xiàn)其handlerMessage()方法用于Message的統(tǒng)一處理绰播。返回值表示是否攔截。


image

3.缺點(diǎn):無法攔截Runnable消息

5.Handler 發(fā)送延遲消息,涉及哪些?法呵萨?原理是什么?會(huì)被開機(jī)時(shí)間影響嗎忱嘹?

1.涉及方法:sendMessageDelayed()和sendMessageAtTime(),最終都會(huì)調(diào)?到 enqueueMessage() ?隊(duì)础米;


image

image
  1. 原理:延遲時(shí)間記錄在 msg.when 中医寿,參與 MessageQueue 的優(yōu)先級(jí)排序,即 MQ.enqueueMessage() 插?消息時(shí)沟突,會(huì)基于 when 計(jì)算消息在 MessageQueue 中的位置并插?;


    image

    image

    3.不受開機(jī)時(shí)間影響,因其延遲消息基于 SystemClock条霜,此為設(shè)備開機(jī)時(shí)間宰睡,不受時(shí)鐘影響 旋圆。
    1.prepare不同
    主線程:prepareMainLooper()
    子線程:prepare()
    2.是否允許退出
    主線程:不允許
    子線程:允許
    3.構(gòu)造方法不同
    主線程:有ActivityThread啟動(dòng)時(shí),main()方法中構(gòu)造的刻肄,開發(fā)者無需關(guān)系
    子線程:開發(fā)者執(zhí)行構(gòu)造,prepare() --->loop()

new Thread(){
    public void run() {
        Looper.prepare();
        Toast.makeText(MainActivity.this, "Hello", 0).show();
        Looper.loop();
    };  
}.start();

7.Looper 如何保證線程唯?绿饵?線程內(nèi)多次 prepare() 不同的 Looper 會(huì)怎樣?

1.原理:基于 TLS 機(jī)制要门,Looper ?次 prepare() 時(shí),會(huì)將 Looper 存? ThreadLocal (map)中炒瘟,再
次 prepare() 時(shí)檢查 ThreadLocal 是否已存儲(chǔ);


image

2.多次調(diào)? Looper prepare() 會(huì)拋出異常廓推;

8.Looper 如何判斷是否允許退出?如何設(shè)置 Looper 是否允許退出专缠?主線程 Looper 允許退出嗎?

1.判斷:Looper持有的MessageQueue的mQuitAllow狀態(tài),標(biāo)識(shí)了是否允許退出

image

2.設(shè)置:通過 Looper.prepare(quitAllowed) 的?參 quitAllowed 判斷是否允許退出渔工;
此?法為私有,外部?法直接調(diào)?兰吟;
3.規(guī)律:主線程 Looper 不允許退出混蔼,?線程 Looper 允許退出;

  1. 主線程:prepareMainLooper() → prepare(false) - 不允許退出晚吞;


    image

    2.其他線程:prepare() → prepare(true) - 允許退出;

9.Looper 的退出捌蚊,涉及哪些?法,原理是什么窗宦?有什么限制沐扳?

1.Api:直接退出quit() & 安全退出quitSafey()


image

2.原理:都會(huì)調(diào)? MessageQueue 的 quit() ?法,清理 MessageQueue 持有的消息躯嫉,并標(biāo) 記 MQ 退出哄陶,驅(qū)動(dòng)其 next() ?法返回 null蜒谤,初始 Looper 退出 loop() 循環(huán)资锰,進(jìn)?使得 Looper 退出;


image

image

3.限制:只有?線程 Looper 才允許退出,主線程 Looper 嘗試退出會(huì)拋出異常;

4.Tips:MQ 退出 → () 返回 null → Looper.loop() 收到 null → 跳出while 循環(huán) → Looper 退出鹃两;

10.Looper.loop() ?法中的循環(huán)內(nèi),調(diào)? MessageQueue 的 next(),若 next() 返回 null 則直接 退出循環(huán)梯醒,合理嗎?

1.合理
2.正常情況,MQ,next() 必然會(huì)返回待處理的消息猫胁,沒有則會(huì)通過 nativePollOnce() 休眠


image

image

3.若 next() 返回 null,則說明出現(xiàn)異常
mPtr = 0盼樟,消息隊(duì)列已被清理并退出;
mQuitting = true,消息隊(duì)列已經(jīng)被標(biāo)記為退出稍途;

11.如何構(gòu)造子線程Looper?涉及哪些方法装盯?

  1. 啟動(dòng)新線程迄损;
  2. 調(diào)? Looper.prepare() - 準(zhǔn)備垮抗;
    3.調(diào)? Looper.loop() - 進(jìn)?循環(huán)液茎;
new Thread(){
   public void run() {
       Looper.prepare();
       Toast.makeText(MainActivity.this, "Hello", 0).show();
       Looper.loop();
   };  
}.start();

12.主線程 Looper 何時(shí)運(yùn)?欲间?

1.App啟動(dòng)時(shí),會(huì)調(diào)用到ActivityThread周达址,Looper就在其main()方法中被啟動(dòng)


image

2.main()中會(huì)調(diào)用Looper,prepareMainLooper()和Looper.loop()


image

3.Tips:ActivityThread 不繼承? Thread满葛,它只是?個(gè)運(yùn)?在主線程上的對(duì)象缠捌;
image

13.Message 消息池的結(jié)構(gòu)?最?緩存多少個(gè) Message 對(duì)象?

1.Message類的靜態(tài)屬性sPool維護(hù)
2.消息池基于鏈表結(jié)構(gòu)蹦魔,以msg.next串聯(lián)
3.sPoolSize 維護(hù)消息池??,最? 50;


image

14.Message 消息池,有什么優(yōu)點(diǎn)玩般?

1.享元模式,避免重復(fù)構(gòu)造Message
2.回收資源洒忧,回收時(shí)清理msg持有的callback和target,避免內(nèi)存泄漏

15.Handler 的 Message 可以分為那 3 類?分別有什么標(biāo)識(shí)芝雪?

1.同步Message:普通Message
2.異步Message:msg.setAsynchronous(true)


image

3.同步屏障:msg.target == null


image

16.同?個(gè) Message 對(duì)象能否重復(fù) send?

1.關(guān)鍵在于如何定義同一個(gè)Message
2.角度一:Java對(duì)象層面晤柄,可被復(fù)用
原因:Message由消息池維護(hù)芥颈,即同一個(gè)對(duì)象被回收后會(huì)被再次復(fù)用

new Message & Message.obtain() 

3.角度二:業(yè)務(wù)層面盾计,不能復(fù)用署辉;
原因:Message通過enqueueMessage()入隊(duì)時(shí)炫乓,會(huì)通過markInUse()標(biāo)記,再次入隊(duì)無法通過isInUse()檢查,則會(huì)拋出異常

image

17.場(chǎng)景:MessageQueue 是基于觸發(fā)時(shí)間 when 的優(yōu)先級(jí)隊(duì)列安吁,那么什么情況下黔龟,隊(duì)列中靠后 的消息會(huì)優(yōu)先得到執(zhí)?巍棱?原理是什么到踏?

1.場(chǎng)景:靠前的消息是同步消息谊路,靠后的消息是異步消息,且消息隊(duì)列的隊(duì)頭為同步屏障

  1. 原理:同步屏障會(huì)阻塞 MQ 中的同步消息,優(yōu)先處理異步消息免都;

18.Message 的同步屏障有什么??有什么意義?如何發(fā)送?個(gè)同步屏障?

1.用途:阻塞MQ對(duì)同步Message的分發(fā),target == null ,無法通過 Handler ?隊(duì)出隊(duì)凿菩,需直接操作 MQ
2.意義:允許異步消息優(yōu)先于同步消息執(zhí)?获黔;
3.同步屏障:特殊的 Message玷氏,target == null赞辩,?法通過 Handler ?隊(duì)出隊(duì),需直接操作 MQ谷朝;
?隊(duì):postSyncBarrier():返回?個(gè)屏障 token送朱;
出隊(duì):removeSyncBarrier()


image

image

image

19.什么是異步消息?如何發(fā)送?

1.意義:需配合同步屏障使?垦缅,否者與同步消息?區(qū)別

  1. 異步消息:setAsynchronous(true) → 向 flags 添加 FLAG_ASYNCHRONOUS 標(biāo)記


    image

    image

    3.發(fā)送?式
    通過異步 Handler 發(fā)送 → 構(gòu)造 Handler 時(shí),async 傳遞 true
    發(fā)送消息前,主動(dòng)調(diào)? setAsynchronous(true)
    ---安全起?漫试,Android 9.0 普通開發(fā)者?法使?異步消息,所有發(fā)送?式被標(biāo)記為 @hide

20.同步屏障如何配合異步消息?作?

1.當(dāng) mMessage 是?個(gè)同步屏障時(shí)勘究,會(huì)跳過所有同步消息十办,找到異步消息提前執(zhí)?
2.若 MQ 隊(duì)列中沒有異步消息,會(huì)進(jìn)? nativePollOnce(mPtr, -1) ?限等待超棺,直到同步屏障
被移除向族,或新的異步消息?隊(duì),才會(huì)通過 nativeWake() 喚醒 MQ适肠;


image

21.Handler 的 IdleHandler 機(jī)制,如何理解喷众?有什么?途?

1.接?斟览,需實(shí)現(xiàn) queueIdle() ?法 & 定義在 MQ 中 & 以 MQ mIdleHandlers 維護(hù)存儲(chǔ)


image

2.?途:可在 MQ 即將空閑時(shí),處理任務(wù)


image

3.邏輯點(diǎn):MQ.next() 中,當(dāng)前?待執(zhí)?消息時(shí),執(zhí)? mIdleHandlers缠诅;如上圖
4.依據(jù) queueIdle() 返回值分:持續(xù)回調(diào)(true) & ?次性回調(diào)(false),false 會(huì)導(dǎo)致執(zhí)? 完后核芽,從 mIdleHandlers 中移除 分飞。如上圖

22.IdleHandler 的 queueIdle() 返回 true,為什么不會(huì)死循環(huán)?

  1. pendingIdleHandlerCount 標(biāo)記控制靠汁,MQ.next() 時(shí)概荷,初始為 -1误证;


    image

    2.-1 才會(huì)執(zhí)? mIdleHandlers芦昔,執(zhí)?后置為 0 → 不會(huì)重復(fù)執(zhí)?


    image

    3.每次 Looper.loop() 從 MQ.next() 取出消息后寡润,在 Loop 循環(huán)中繼續(xù)調(diào)? MQ.next() 才會(huì)重 置pendingIdleHandlerCount,才會(huì)繼續(xù)執(zhí)?

23.IdleHandler 執(zhí)?耗時(shí)會(huì)影響正常的消息分發(fā)嗎舅柜?Handler 內(nèi)部如何處理梭纹?

1.會(huì)
2.IdleHandler的耗時(shí)不可控
3.執(zhí)?完后會(huì)重置 nextPollTimeoutMillis = 0,重新分發(fā)最近消息

24.Handler 在 Activity 中使?致份,什么場(chǎng)景下會(huì)出現(xiàn)內(nèi)存泄露变抽?原因是什么?如何規(guī)避氮块?

1.現(xiàn)場(chǎng):延遲消息 + 內(nèi)部類 Handler绍载;導(dǎo)致Handler 持有外部類的對(duì)象
2.主線程?命周期?于四?組件,msg,target 指向 Handler滔蝉,? Handler 作為內(nèi)部類 持有外部類 Activity 的引?击儡,導(dǎo)致 Activity 泄露


image

  1. 1, 靜態(tài) Handler + Activity 弱引?;
    1. 隨 Activity ?命周期锰提,onDestory() 會(huì) remove 掉所有的消息

25.移除消息的 removeMessage() 為什么需要兩次循環(huán)曙痘?

1.優(yōu)化效率

  1. while-1:移除消息 & 找到下?個(gè)待處理的消息芳悲,存? mMessages 中;
  2. while-2:從 mMessages 開始边坤,移除后續(xù)符合條件的消息


    image

25.如何理解 HandlerThread名扛?

1.繼承 Thread,內(nèi)部持有 Handler茧痒,并?維護(hù)?線程的 Looper
2.意義:將 Thread肮韧、Handler、Looper 封裝旺订,便于開發(fā)者使?


image

26.如何實(shí)現(xiàn)弄企,?線程等待主線程處理消息結(jié)束后,再繼續(xù)執(zhí)?区拳?原理是什么拘领?

1.借助 Handler 的 runWithScissors()
2.原理:內(nèi)部通過 BlockingRunnbale 包裝,通過 synchronized + wait 進(jìn)?等待樱调,在 r 執(zhí)?
完成后约素,調(diào)? notifyAll() 喚醒等待隊(duì)列,?線程收到后繼續(xù)執(zhí)?


image

image

image

27.Handler 的 runWithScissors() 可實(shí)現(xiàn) A 線程阻塞等待 B 線程處理完消息后再繼續(xù)執(zhí)?的功 能笆凌,它為什么被標(biāo)記為 hide圣猎?存在什么問題?原因是什么乞而?

1.實(shí)現(xiàn):將 Runnable 包裝為 BlockingRunnable送悔,其內(nèi)通過 synchronized + wait 進(jìn)?等
待,待 r 執(zhí)?完后爪模,調(diào)? notifyAll() 喚醒等待隊(duì)列的?線程欠啤,?線程繼續(xù)執(zhí)?(如上圖)

2.問題:在?線程 Looper 中使?,可能導(dǎo)致 A 線程進(jìn)? wait 等待呻右,?永遠(yuǎn)得不到被 notify喚醒

3.原因:?線程 Looper 允許退出跪妥,若包裝的 BlockingRunnable 被執(zhí)?前,MessageQueue
退出,則該 runnable 永遠(yuǎn)不會(huì)被執(zhí)?吧趣,則會(huì)導(dǎo)致 A 線程?直處于 wait 等待遍膜,永遠(yuǎn)不會(huì)被notify 喚醒

28.?線程如何向主線程的 Handler 發(fā)送消息?為什么經(jīng)過 Handler 就可以達(dá)到切線程的?的乒省?

1.在 Android 中,主線程主要承擔(dān)更新 UI 的?作,耗時(shí)操作?法在主線程完成

2.?作線程可以通過向主線程的 Handler 發(fā)?消息憾赁,來達(dá)到與主線程通信的?的

3.主線程與?作線程之間,是共享內(nèi)存地址空間的散吵,所以是可以互相操作的龙考,但是需要注意處理線程同步的問題

4.?作線程通過主線的 Handler蟆肆,向其成員變量 MessageQueue 中添加 Message。同時(shí)主
線程的 Looper ?直處于 loop() 狀態(tài)晦款,當(dāng)檢測(cè)到有新 Message 時(shí)炎功,會(huì)將其取出,并通過
dispatchHandler() 分發(fā)處理消息


image

29.Looper.loop 中缓溅,如果沒有待處理的消息蛇损,為什么不會(huì)阻塞 UI?

1.主線程在 MessageQueue 沒有消息時(shí)坛怪,會(huì)阻塞在 loop 的 queue.next() ?法中的 nativePollOnce()?法?
2.此時(shí)主線程會(huì)釋放 CPU 資源進(jìn)?休眠狀態(tài)淤齐,直到下?個(gè)消息到達(dá)或者有事務(wù)發(fā)?,通過

往 pipe 管道寫端寫?數(shù)據(jù)的?式袜匿,來喚醒主線程更啄。這?采?的是 epoll 機(jī)制

3.epoll 機(jī)制是?種 IO 多路復(fù)?機(jī)制,可以同時(shí)監(jiān)控多個(gè)描述符居灯,在有事件發(fā)?的時(shí)候祭务,?

即通知相應(yīng)程序進(jìn)?讀或?qū)懖僮鳎愃?種 callback 的回調(diào)機(jī)制穆壕。

4.主線程在?多數(shù)時(shí)候是處于休眠狀態(tài)待牵,并不會(huì)消耗?量的 CPU 資源。當(dāng)有新的消息或事

務(wù)到達(dá)時(shí)喇勋,會(huì)?即喚醒主線程進(jìn)?處理缨该,所以對(duì)?戶來說是?感知的

30.Handle MQ ?消息時(shí),為什么不出現(xiàn) ANR川背?

1.ANR 機(jī)制有獨(dú)特的覆蓋場(chǎng)景贰拿,通常原因?yàn)樘幚硐⒉患皶r(shí)

2.MQ ?消息時(shí),會(huì)進(jìn)? nativePollOnce() 休眠熄云,此時(shí)?消息膨更,處于休眠狀態(tài)

3.MQ 有消息時(shí),會(huì)?即通過 nativeWake() 喚醒去處理消息

31.如果 Java 層 MQ 中消息很少缴允,但是響應(yīng)時(shí)間卻很?荚守,是什么原因?

1.MQ隊(duì)列中练般,該Message前的Message處理較為耗時(shí)

2.Native 層消息過多矗漾,Java層MQ消息優(yōu)先級(jí)最低,最后處理

32.在完整的 Handler (Java & C++)架構(gòu)下薄料,消息處理的優(yōu)先級(jí)?

1.Native Message

2.Native Request

3.Java Message
Natitv的優(yōu)先級(jí)最高敞贡,Java的最低

33.Native 層的 MQ,提供了哪些 JNI ?法摄职?各有什么?途誊役?

nativeInit():初始化
1.創(chuàng)建了 NativeMessageQueue 對(duì)象获列,增加其引?計(jì)數(shù),并將 NativeMessageQueue
指針 mPtr 保存在 Java 層的 MessageQueue蛔垢。

image

2.創(chuàng)建 Native Looper 對(duì)象(如上圖)
3.調(diào)? epoll 的 epoll_create()/ epoll_ctl() 來完成對(duì) mWakeEventFd 和 mRequests 的可 讀事件監(jiān)聽击孩。
image

image

nativeDestory():回收資源
1. 調(diào)? RefBase::decStrong() 來減少對(duì)象的引?計(jì)數(shù)
2.當(dāng)引?計(jì)數(shù)為 0 時(shí),則刪除 NativeMessageQueue 對(duì)象啦桌。
nativePollOnce():利? epoll 機(jī)制休眠溯壶,等待被喚醒
調(diào)? Looper::pollOnce() 來完成,空閑時(shí)停留在 epoll_wait() ?法甫男,?于等待事件發(fā)?或 超時(shí)
image

//1且改、等待事件發(fā)生或者超時(shí)(timeoutMillis),如果有事件發(fā)生板驳,就從管道中讀取事件放入事件集合(eventItems)返回又跛,如果沒有事件發(fā)生,進(jìn)入休眠等待若治,如果timeoutMillis時(shí)間后還沒有被喚醒慨蓝,就會(huì)返回
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
nativeWake():向管道 mWakeEventFd 寫?字符 1,喚醒 epoll_wait() 等待
image

image

34.如何理解 Looper 的 Painter端幼?

  1. 在 Looper.loop() 循環(huán)消息的時(shí)候礼烈,如果 mLogging 不為 null,都會(huì)在關(guān)鍵點(diǎn)通過 Printer 輸出 Log婆跑。例如 Message 開始執(zhí)?和執(zhí)?完畢


    image

    2.Printer 對(duì)象在 Looper 中默認(rèn)為 null此熬,可以通過 setMessageLogging() ?法從外部設(shè)置


    image

    3.性能檢測(cè)?具 BlockCanary 就是利? Printer 來檢測(cè)主線程卡頓的問題。通過處理

Message 兩次 Log 的時(shí)間差值滑进,來判斷是否存在卡頓

35.Looper 的 Printer 輸出的?志犀忱,有什么其他?途?依靠的原理是什么扶关?有什么缺點(diǎn)阴汇?

1.?途:性能監(jiān)控;

2.原理:通過篩選?志內(nèi)存节槐,區(qū)分 Message 的開始執(zhí)?和結(jié)束執(zhí)?的時(shí)間點(diǎn)搀庶,即可判斷處 理 Message 的耗時(shí),即主線程卡頓耗時(shí)铜异;

3.缺點(diǎn):Printer 存在?量字符串拼接地来,在消息量?時(shí),會(huì)導(dǎo)致性能受損熙掺;
實(shí)測(cè)數(shù)據(jù):存在 Printer 時(shí),在列表快速滑動(dòng)時(shí)咕宿,平均幀率降低 5 幀币绩;

36.如何理解 epoll蜡秽?它有什么優(yōu)勢(shì)(Android M 開始,將 Pipe 換成了 eventFd)缆镣?

1.Linux 的 I/O 多路復(fù)?機(jī)制芽突,可以同時(shí)監(jiān)控多個(gè)描述符;

2.多路復(fù)?機(jī)制下董瞻,可以通知內(nèi)核掛起進(jìn)程/線程寞蚌,當(dāng) 1 個(gè) 或多個(gè) IO 事件發(fā)?后,內(nèi)核再喚 醒進(jìn)程钠糊,將控制權(quán)返還挟秤,由應(yīng)?程序??處理事件;
3.epoll 優(yōu)勢(shì):
(1)監(jiān)控描述符數(shù)量不受限抄伍;
監(jiān)控 fd 數(shù)量何內(nèi)存相關(guān)艘刚,3G 內(nèi)存 → 20w~30w
(2)IO 不會(huì)隨監(jiān)控 fd 的增多?放? → 得益于事件表維護(hù) fd 與其回調(diào)的關(guān)系;
4.epoll 適?:

1.適??量空閑連接的場(chǎng)景 

2.沒有?量空閑或死亡連接時(shí)截珍,epoll 的效率不會(huì)? select/poll ? → 量?時(shí) O(logn) 和 

O(n) 差別不?

5.操作

1.epoll_create - 創(chuàng)建 epoll 句柄攀甚; 

2.epoll_ctl() - 設(shè)置監(jiān)聽的 fd; 

3.epoll_wait() - 等待 fd 事件岗喉;

37.Handler 和管道(Pipe)的關(guān)系(Android M 開始秋度,將 Pipe 換成了 eventFd)?

1.Handler 底層的休眠機(jī)制钱床,就是利?管道 和 epoll 的 I/O 多路復(fù)?

2.線程進(jìn)?休眠荚斯,通過 nativePollOnce() 底層調(diào)? epoll_wait() 進(jìn)?休眠

3.A 線程準(zhǔn)備好 Message 后,放?消息池诞丽,向管道寫?數(shù)據(jù) “1”鲸拥,管道有數(shù)據(jù)后,會(huì)喚醒?

標(biāo)線程去處理消息

4.Tips:Android M 開始僧免,將 Pipe 換成了 eventFd刑赶;


image

38.Handler 底層為什么使?管道,?不是 Binder懂衩?

1.相對(duì)于同進(jìn)程內(nèi)的線程通信撞叨,Binder 太重了,浪費(fèi) CPU 和內(nèi)存資源(Binder 消耗CPU大)

2.內(nèi)存?度:Binder 通信涉及?次內(nèi)存拷?浊洞,?多個(gè)線程操作的 Handler 是在共享的內(nèi)存

中牵敷,?需拷?,只需要通知線程有數(shù)據(jù)了

3.CPU ?度:Binder 底層驅(qū)動(dòng)會(huì)維護(hù)線程池法希,?較浪費(fèi) CPU 資源

39.Handler 可以 IPC 通信(進(jìn)程間的通信)嗎枷餐?

1.不能

2.Handler 只能?于共享內(nèi)存地址的 2 個(gè)線程通信,即同進(jìn)程的 2 個(gè)線程通信苫亦;

40.Handler 為什么需要使?底層的 epoll 來休眠毛肋?

1.需要兼顧 Native 層的消息怨咪,消息可能來?底層硬件(分層方式當(dāng)中,Native層就是本地框架)

2.如果只考慮 Java 層润匙,notify/wait 即可實(shí)現(xiàn)

41.如何理解 nativePollOnce() ?法诗眨?

1.最終會(huì)調(diào)?到 Native 層的 pollInner() ?法。

2.在 pollInner() 中孕讳,處理流程:

a. 先調(diào)? epoll_wait()匠楚,這是阻塞?法,?戶等待事件發(fā)?或超時(shí)厂财。 

b. 對(duì)于 epoll_wait() 返回芋簿,當(dāng)且僅當(dāng)?下三種情況出現(xiàn)時(shí),才會(huì)返回蟀苛。 

    POLL_ERROR益咬,發(fā)?錯(cuò)誤,直接跳轉(zhuǎn)到 Done帜平。 

    POLL_TIMEOUT幽告,發(fā)?超時(shí),直接跳轉(zhuǎn)到 Done裆甩。 

    檢測(cè)到管道有事件發(fā)?冗锁,則根據(jù)情況做響應(yīng)的處理 

        如果是管道有事件發(fā)?,則直接讀取管道的數(shù)據(jù)嗤栓。 

        如果是其他事件冻河,則處理 request,?成對(duì)應(yīng)的 response 對(duì)象茉帅,push 到 

        response 數(shù)組叨叙。 

c. 進(jìn)? Done 標(biāo)記為的代碼段。

  先處理 Native 的 Message堪澎,調(diào)? Native 的 Handler 來處理 Message擂错。 

  再處理 Response 數(shù)組,POLL_CALLBACK 類型的事件樱蛤。 

d. 返回后钮呀,Java 層繼續(xù)處理


image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市昨凡,隨后出現(xiàn)的幾起案子爽醋,更是在濱河造成了極大的恐慌,老刑警劉巖便脊,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚂四,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)证杭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門田度,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人解愤,你說我怎么就攤上這事『趵颍” “怎么了送讲?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)惋啃。 經(jīng)常有香客問我哼鬓,道長(zhǎng),這世上最難降的妖魔是什么边灭? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任异希,我火速辦了婚禮,結(jié)果婚禮上绒瘦,老公的妹妹穿的比我還像新娘称簿。我一直安慰自己,他們只是感情好惰帽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布憨降。 她就那樣靜靜地躺著,像睡著了一般该酗。 火紅的嫁衣襯著肌膚如雪授药。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天呜魄,我揣著相機(jī)與錄音悔叽,去河邊找鬼。 笑死爵嗅,一個(gè)胖子當(dāng)著我的面吹牛娇澎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播操骡,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼九火,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了册招?” 一聲冷哼從身側(cè)響起岔激,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎是掰,沒想到半個(gè)月后虑鼎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年炫彩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了匾七。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡江兢,死狀恐怖昨忆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情杉允,我是刑警寧澤邑贴,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站叔磷,受9級(jí)特大地震影響拢驾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜改基,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一繁疤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧秕狰,春花似錦稠腊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至诺舔,卻和暖如春鳖昌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背低飒。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國打工许昨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人褥赊。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓糕档,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親拌喉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子速那,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容