android線程通信方式
⑴ Android多線程的四種方式:Handler、AsyncTask、ThreadPoolExector、IntentService
非同步通信機制,將工作線程中需更新UI的操作信息 傳遞到 UI主線程,從而實現 工作線程對UI的更新處理,最終實現非同步消息的處理。Handler不僅僅能將子線程的數據傳遞給主線程,它能實現任意兩個線程的數據傳遞。
(1)Message
Message 可以在線程之間傳遞消息。可以在它的內部攜帶少量數據,用於在不同線程之間進行數據交換。除了 what 欄位,還可以使用 arg1 和 arg2 來攜帶整型數據,使用 obj 來攜帶 Object 數據。
(2) Handler
Handler 作為處理中心,用於發送(sendMessage 系列方法)與處理消息(handleMessage 方法)。
(3) MessageQueue
MessageQueue 用於存放所有通過 Handler 發送的消息。這部分消息會一直存放在消息隊列中,直到被處理。每個線程中只會有一個 MessageQueue 對象
(4) Looper
Looper 用於管理 MessageQueue 隊列,Looper對象通過loop()方法開啟了一個死循環——for (;;){},不斷地從looper內的MessageQueue中取出Message,並傳遞到 Handler 的 handleMessage() 方法中。每個線程中只會有一個 Looper 對象。
AsyncTask 是一種輕量級的任務非同步類,可以在後檯子線程執行任務,且將執行進度及執行結果傳遞給 UI 線程。
(1)onPreExecute()
在 UI 線程上工作,在任務執行 doInBackground() 之前調用。此步驟通常用於設置任務,例如在用戶界面中顯示進度條。
(2)doInBackground(Params... params)
在子線程中工作,在 onPreExecute() 方法結束後執行,這一步被用於在後台執行長時間的任務,Params 參數通過 execute(Params) 方法被傳遞到此方法中。任務執行結束後,將結果傳遞給 onPostExecute(Result) 方法,同時我們可以通過 publishProgress(Progress) 方法,將執行進度發送給 onProgressUpdate(Progress) 方法。
(3)onProgressUpdate(Progress... values)
在 UI 線程上工作,會在 doInBackground() 中調用 publishProgress(Progress) 方法後執行,此方法用於在後台計算仍在執行時(也就是 doInBackgound() 還在執行時)將計算執行進度通過 UI 顯示出來。例如,可以通過動畫進度條或顯示文本欄位中的日誌,從而方便用戶知道後台任務執行的進度。
(4)onPostExecute(Result result)
在 UI 線程上工作,在任務執行完畢(即 doInBackground(Result) 執行完畢)並將執行結果傳過來的時候工作。
使用規則:
(1)AsyncTask 是個抽象類,所以要創建它的子類實現抽象方法
(1)AsyncTask 類必須是在 UI 線程中被載入,但在Android 4.1(API 16)開始,就能被自動載入完成。
(2)AsyncTask 類的實例對象必須在 UI 線程中被創建。
(3)execute() 方法必須是在 UI 線程中被調用。
(4)不要手動調用方法 onPreExecute()、onPostExecute()、doInBackground()、onProgressUpdate()
(5)任務只能執行一次(如果嘗試第二次執行,將拋出異常)。即一個AsyncTask對象只能調用一次execute()方法。
原理:
其源碼中原理還是 Thread 與 Handler 的實現,其包含 兩個線程池,一個 Handler,如下所示:
名稱類型作用
SERIAL_EXECUTOR線程池分發任務,串列分發,一次只分發一個任務
THREAD_POOL_EXECUTOR線程池執行任務,並行執行,執行的任務由 SERIAL_EXECUTOR 分發
InternalHandlerHandler負責子線程與主線程的溝通,通知主線程做 UI 工作
一方面減少了每個並行任務獨自建立線程的開銷,另一方面可以管理多個並發線程的公共資源,從而提高了多線程的效率。所以ThreadPoolExecutor比較適合一組任務的執行。Executors利用工廠模式對ThreadPoolExecutor進行了封裝。
Executors提供了四種創建ExecutorService的方法,他們的使用場景如下:
1. Executors.newFixedThreadPool()
創建一個定長的線程池,每提交一個任務就創建一個線程,直到達到池的最大長度,這時線程池會保持長度不再變化。
當線程處於空閑狀態時,它們並不會被回收,除非線程池被關閉。當所有的線程都處於活動狀態時,新任務都會處於等待狀態,直到有線程空閑出來。
只有核心線程並且不會被回收,能夠更加快速的響應外界的請求。
2. Executors.newCachedThreadPool()
創建一個可緩存的線程池,如果當前線程池的長度超過了處理的需要時,它可以靈活的回收空閑的線程,當需要增加時,它可以靈活的添加新的線程,而不會對池的長度作任何限制
線程數量不定的線程池,只有非核心線程,最大線程數為 Integer.MAX_VALUE。當線程池中的線程都處於活動狀態時,線程池會創建新的線程來處理新任務,否則利用空閑的線程來處理新任務。線程池中的空閑線程具有超時機制,為 60s。
任務隊列相當於一個空集合,導致任何任務都會立即被執行,適合執行大量耗時較少的任務。當整個線程池都處於限制狀態時,線程池中的線程都會超時而被停止。
3. Executors.newScheledThreadPool()
創建一個定長的線程池,而且支持定時的以及周期性的任務執行,類似於Timer。
非核心線程數沒有限制,並且非核心線程閑置的時候立即回收,主要用於執行定時任務和具有固定周期的重復任務。
4. Executors.newSingleThreadExecutor()
創建一個單線程化的executor,它只創建唯一的worker線程來執行任務
只有一個核心線程,保證所有的任務都在一個線程中順序執行,意義在於不需要處理線程同步的問題。
一般用於執行後台耗時任務,當任務執行完成會自動停止;同時由於它是一個服務,優先順序要遠遠高於線程,更不容易被系統殺死,因此比較適合執行一些高優先順序的後台任務。
使用步驟:創建IntentService的子類,重寫onHandleIntent方法,在onHandleIntent中執行耗時任務
原理:在源碼實現上,IntentService封裝了HandlerThread和Handler。onHandleIntent方法結束後會調用IntentService的stopSelf(int startId)方法嘗試停止服務。
IntentService的內部是通過消息的方式請求HandlerThread執行任務,HandlerThread內部又是一種使用Handler的Thread,這就意味著IntentService和Looper一樣是順序執行後台任務的
(HandlerThread:封裝了Handler + ThreadHandlerThread適合在有需要一個工作線程(非UI線程)+任務的等待隊列的形式,優點是不會有堵塞,減少了對性能的消耗,缺點是不能同時進行多個任務的處理,需要等待進行處理。處理效率低,可以當成一個輕量級的線程池來用)
⑵ android中什麼時候會選擇用廣播來進行線程間的通信
android中什麼時候會選擇用廣播來進行線程間的通信 Android 多線程 通信
線程中通信就不要用廣播了吧 進程中通信可以用廣播或者aidl
可是,這兩天看到的項目都是這么做的;然後,自己分析了下,覺得一下的理由也是可以成立的;
1.正常情況下我們選擇handler消息機制來進行單向的線程間的通信;(工作線程向主線程發送消息)
因為主線程有現成的handler,而工作線程沒有現成的handler,這樣的話,主線程將handler交給工作線程而讓工作線程將工作的結果交給主線程;
相反,工作線程中沒有現成的handler(事實上是沒有消息隊列,也就是handler沒有綁定到工作線程),那麼,如果開辟的話,代碼角度上是挺麻煩的(相對應廣播機制來說);
2.廣播機制本身就是雙向的(工作線程向主線程發送廣播,主線程向工作線程發送廣播);
//另外,對於像一個activity中通過fragment來進行界面的處理; 我們大多數情況下是採用廣播的機制來實現fragment中adapter的數據的更新;這樣做主要是考慮到工作線程的任務載入完成,而具體的對應刷新的activity可能還沒有啟動;
另外,基於介面隔離原則,如果用handler進行通信的話,則不能很好的滿足這一原則;
你要是周期比較長 用廣播好些吧
應該與周期關系不是很密切。最主要的原因是兩條線成是雙向通信。
Handler類似於P2P的通信。
廣播則類似於一個server端,用來處理分發不同線程的請求,從控制器的角度來說用廣播更好一點。
一般使用Handler的,多用於子線程處理事務,完成時告知主線程這一類的情況。
而類似樓主所說的多條線程之間需要頻繁交互的話,廣播是個很好的選擇,並且結構清晰,只是不知道廣播的性能與handler相比會怎麼樣。
⑶ Android進程與線程區別
所以下來特地去查了以下資料,先說說線程:
(1)在Android APP中,只允許有一個主線程,進行UI的渲染等等,但是不能進行耗時操作(網路交互等等),否則會造成ANR,就是線程阻塞卡死,未響應。
(2)除了主線程之外,耗時操作都應該規范到子線程中,線程之間會有相應的通信方式,但相互獨立。
(3)然後看了一下所查資料:
線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。線程比進程更小,基本上不擁有系統資源,故對它的調度所用資源小,能更高效的提高系統內多個程序間並發執行的。 嗯,從大的說就是這樣。
在平時的Android開發過程中,基本上都會用到線程handler,thread等等,具體的實現方法我就不在這里寫了。
進程:
根據所查資料:是一個具有獨立功能的程序關於某個數據集合的一次運行活動。進程是系統進行資源分配和調度的一個獨立單位。可以申請和擁有系統資源,是一個動態的概念,是一個活動的實體,是一個「執行中的程序」。不只是程序的代碼,還包括當前的活動。
這應該是一個比較大的概念,存在於一個系統中,與線程的區別是:
1、子進程和父進程有不同的代碼和數據空間,而多個線程則共享數據空間,每個線程有自己的執行堆棧和程序計數器為其執行上下文。
2、進程間相互獨立,同一進程的各線程間共享。某進程內的線程在其它進程不可見。
3、進程間通信IPC,線程間可以直接讀寫進程數據段(如全局變數)來進行通信——需要進程同步和互斥手段的輔助,以保證數據的一致性。
4、線程上下文切換比進程上下文切換要快得多。
⑷ Android:主線程如何向子線程發送消息
因為你是在主線程創建的handler實例,比如你是這樣實例化handler
然後調用looper.loop();就開始了消息循環。這就是為什麼在主線程發消息住線程還能收到消息的原因。因為發送消息的實例是在主線程實例化的就有了主線程的looper。
⑸ 面試被問到android中兩個子線程怎麼通信,我懵了。
構造HandlerThread類的對象mHandlerThread,這樣生成一個子線程可以調用new MyHandler(mHandlerThread.getLooper())來獲取子線程的handler,另一個子線程發消息,收到消息的就是子線程而不是主線程了。
⑹ [Android源碼分析] - 非同步通信Handler機制
一、問題:在Android啟動後會在新進程里創建一個主線程,也叫UI線程( 非線程安全 )這個線程主要負責監聽屏幕點擊事件與界面繪制。當Application需要進行耗時操作如網路請求等,如直接在主線程進行容易發生ANR錯誤。所以會創建子線程來執行耗時任務,當子線程執行完畢需要通知UI線程並修改界面時,不可以直接在子線程修改UI,怎麼辦?
解決方法:Message Queue機制可以實現子線程與UI線程的通信。
該機制包括Handler、Message Queue、Looper。Handler可以把消息/ Runnable對象 發給Looper,由它把消息放入所屬線程的消息隊列中,然後Looper又會自動把消息隊列里的消息/Runnable對象 廣播 到所屬線程里的Handler,由Handler處理接收到的消息或Runnable對象。
1、Handler
每次創建Handler對象時,它會自動綁定到創建它的線程上。如果是主線程則默認包含一個Message Queue,否則需要自己創建一個消息隊列來存儲。
Handler是多個線程通信的信使。比如在線程A中創建AHandler,給它綁定一個ALooper,同時創建屬於A的消息隊列AMessageQueue。然後在線程B中使用AHandler發送消息給ALooper,ALooper會把消息存入到AMessageQueue,然後再把AMessageQueue廣播給A線程里的AHandler,它接收到消息會進行處理。從而實現通信。
2、Message Queue
在主線程里默認包含了一個消息隊列不需要手動創建。在子線程里,使用Looper.prepare()方法後,會先檢查子線程是否已有一個looper對象,如果有則無法創建,因為每個線程只能擁有一個消息隊列。沒有的話就為子線程創建一個消息隊列。
Handler類包含Looper指針和MessageQueue指針,而Looper里包含實際MessageQueue與當前線程指針。
下面分別就UI線程和worker線程講解handler創建過程:
首先,創建handler時,會自動檢查當前線程是否包含looper對象,如果包含,則將handler內的消息隊列指向looper內部的消息隊列,否則,拋出異常請求執行looper.prepare()方法。
- 在 UI線程 中,系統自動創建了Looper 對象,所以,直接new一個handler即可使用該機制;
- 在 worker線程 中,如果直接創建handler會拋出運行時異常-即通過查『線程-value』映射表發現當前線程無looper對象。所以需要先調用Looper.prepare()方法。在prepare方法里,利用ThreadLocal<Looper>對象為當前線程創建一個Looper(利用了一個Values類,即一個Map映射表,專為thread存儲value,此處為當前thread存儲一個looper對象)。然後繼續創建handler, 讓handler內部的消息隊列指向該looper的消息隊列(這個很重要,讓handler指向looper里的消息隊列,即二者共享同一個消息隊列,然後handler向這個消息隊列發送消息,looper從這個消息隊列獲取消息) 。然後looper循環消息隊列即可。當獲取到message消息,會找出message對象里的target,即原始發送handler,從而回調handler的handleMessage() 方法進行處理。
- handler與looper共享消息隊列 ,所以handler發送消息只要入列,looper直接取消息即可。
- 線程與looper映射表 :一個線程最多可以映射一個looper對象。通過查表可知當前線程是否包含looper,如果已經包含則不再創建新looper。
5、基於這樣的機制是怎樣實現線程隔離的,即在線程中通信呢。
核心在於 每一個線程擁有自己的handler、message queue、looper體系 。而 每個線程的Handler是公開 的。B線程可以調用A線程的handler發送消息到A的共享消息隊列去,然後A的looper會自動從共享消息隊列取出消息進行處理。反之一樣。
二、上面是基於子線程中利用主線程提供的Handler發送消息出去,然後主線程的Looper從消息隊列中獲取並處理。那麼還有另外兩種情況:
1、主線程發送消息到子線程中;
採用的方法和前面類似。要在子線程中實例化AHandler並設定處理消息的方法,同時由於子線程沒有消息隊列和Looper的輪詢,所以要加上Looper.prepare(),Looper.loop()分別創建消息隊列和開啟輪詢。然後在主線程中使用該AHandler去發送消息即可。
2、子線程A與子線程B之間的通信。
1、 Handler為什麼能夠實現不同線程的通信?核心點在哪?
不同線程之間,每個線程擁有自己的Handler、消息隊列和Looper。Handler是公共的,線程可以通過使用目標線程的Handler對象來發送消息,這個消息會自動發送到所屬線程的消息隊列中去,線程自帶的Looper對象會不斷循環從裡面取出消息並把消息發送給Handler,回調自身Handler的handlerMessage方法,從而實現了消息的線程間傳遞。
2、 Handler的核心是一種事件激活式(類似傳遞一個中斷)的還是主要是用於傳遞大量數據的?重點在Message的內容,偏向於數據傳輸還是事件傳輸。
目前的理解,它所依賴的是消息隊列,發送的自然是消息,即類似事件中斷。
0、 Android消息處理機制(Handler、Looper、MessageQueue與Message)
1、 Handler、Looper源碼閱讀
2、 Android非同步消息處理機制完全解析,帶你從源碼的角度徹底理解
謝謝!
wingjay

⑺ Android的handler機制的原理
Android的handler機制的原理分為非同步通信准備,消息發送,消息循環,消息處理。
1、非同步通信准備
在主線程中創建處理器對象(Looper)、消息隊列對象(Message Queue)和Handler對象。
2、消息入隊
工作線程通過Handler發送消息(Message) 到消息隊列(Message Queue)中。
3、消息循環
消息出隊: Looper循環取出消息隊列(Message Queue) 中的的消息(Message)。
消息分發: Looper將取出的消息 (Message) 發送給創建該消息的處理者(Handler)。
4、消息處理
處理者(Handler) 接收處理器(Looper) 發送過來的消息(Message),根據消息(Message) 進行U操作。
handler的作用
handler是android線程之間的消息機制,主要的作用是將一個任務切換到指定的線程中去執行,(准確的說是切換到構成handler的looper所在的線程中去出處理)android系統中的一個例子就是主線程中的所有操作都是通過主線程中的handler去處理的。
Handler的運行需要底層的 messagequeue和 looper做支撐。
⑻ Android通信方式篇(七)-Binder機制(Native層(下))
本篇文章針對向ServiceManager注冊服務 和 獲取服務兩個流程來做總結。在這兩個過程中,ServiceManager都扮演的是服務端,與客戶端之間的通信也是通過Binder IPC。
在此之前先了解下Binder的進程與線程的關系:
用戶空間 :ProcessState描述一個進程,IPCThreadState對應一個進程中的一個線程。
內核空間 :binder_proc描述一個進程,統一由binder_procs全局鏈表保存,binder_thread對應進程的一個線程。
ProcessState與binder_proc是一一對應的。
Binder線程池 :每個Server進程在啟動時會創建一個binder線程池,並向其中注冊一個Binder線程;之後Server進程也可以向binder線程池注冊新的線程,或者Binder驅動在探測到沒有空閑binder線程時會主動向Server進程注冊新的的binder線程。對於一個Server進程有一個最大Binder線程數限制15,(#define DEFAULT_MAX_BINDER_THREADS 15)。對於所有Client端進程的binder請求都是交由Server端進程的binder線程來處理的。我的理解是:binder線程是進程進行binder ipc時的一條數據處理路徑。
MediaPlayerService向ServiceManager注冊過程如下:
相關類:
整個過程總結如下:
1 獲取BpServiceManager 與 BpBinder
由defaultServiceManager()返回的是BpServiceManager,同時會創建ProcessState對象和BpBinder對象。然後通過BpBinder執行transact,把真正工作交給IPCThreadState來處理。
2 BpBinder transact
Binder代理類調用transact()方法,真正工作還是交給IPCThreadState來進行transact工作。
3 通過IPCThreadState 包裝並轉換數據並進行transact事務處理
每個線程都有一個IPCThreadState,每個IPCThreadState中都有一對Parcel變數:mIn、mOut。相當於兩根數據管道:
最後執行talkWithDriver。
writeTransactionData:將BC Protocol + binder_transaction_data結構體 寫入mOut, 然後執行waitForResponse:
由talkWithDriver將數據進一步封裝到binder_write_read結構體,通過ioctl(BINDER_WRITE_READ)與驅動通信。同時等待驅動返回的接收BR命令,從mIn取出返回的數據。
mIn包裝的數據結構(注冊服務handle = 0 ,code 為ADD_SERVICE_TRANSACTION):
4 Binder Driver
把binder_write_read結構體write_buffer里數據取出來,分別得到BC命令和封裝好數據的事務binder_transaction_data, 然後根據handler,在當前binder_proc中,找到相應的binder_ref,由binder_ref再找到目標binder_node實體,由目標binder_node再找到目標進程binder_proc。然後就是插入數據:當binder驅動可以找到合適的線程,就會把binder_transaction節點插入到servciemanager的線程的todo隊列中,如果找不到合適的線程,就把節點之間插入servciemanager的binder_proc的todo隊列。
5 ServiceManager
經過Binder Driver的處理,數據已經到了ServiceManager進程,在BR_TRANSACTION的引導下,在binder_loop()中執行binder_parser()取出數據,執行do_add_service()操作,最終向 svcinfo 列表中添加已經注冊的服務(沒有數據的返回)。最後發送 BR_REPLY 命令喚醒等待的線程,通知注冊成功。結束MediaPlayerService進程 waitForResponse()的狀態,整個注冊過程結束。
獲取服務的過程與注冊類似,首先 ServiceManager 向 Binder 驅動發送 BC_TRANSACTION 命令攜帶 CHECK_SERVICE_TRANSACTION 命令,同時獲取服務的線程進入等待狀態 waitForResponse()。Binder 驅動收到請求命令向 ServiceManager 的發送 BC_TRANSACTION 查詢已注冊的服務,會區分請求服務所屬進程情況。
查詢到直接響應 BR_REPLY 喚醒等待的線程。若查詢不到將與 binder_procs 鏈表中的服務進行一次通訊再響應。
以startService為例來簡單總結下執行流程:
3.1 從方法執行流程來看:
Client :
1 AMP.startService 標記方法以及通過Parcel包裝數據;
2 BinderProxy.transact 實際調用native的 android_os_BinderProxy_transact 傳遞數據;
3 獲取BpServiceManager 與 BpBinder 同時會創建ProcessState。然後通過BpBinder執行transact,把真正工作交給IPCThreadState來處理;
4 IPC.transact 主要執行writeTransactionData,將上層傳來的數據重新包裝成binder_transaction_data,並將BC Protocol + binder_transaction_data結構體 寫入mOut;
5 IPC waitForResponse talkWithDriver + 等待返回數據;
6 talkWithDriver 將數據進一步封裝成binder_write_read,通過ioctl(BINDER_WRITE_READ)與驅動通信;
Kernel :
7 binder ioctl 接收BINDER_WRITE_READ ioctl命令;
8 binder_ioctl_write_read 把用戶空間數據ubuf拷貝到內核空間bwr;
9 binder_thread_write 當bwr寫緩存有數據,則執行binder_thread_write;當寫失敗則將bwr數據寫回用戶空間並退出;
10 binder_transaction 找到目標進程binder_proc並插入數據到目標進程的線程todo隊列,最終執行到它
時,將發起端數據拷貝到接收端進程的buffer結構體;
11 binder_thread_read 根據binder_transaction結構體和binder_buffer結構體數據生成新的binder_transaction_data結構體,寫入bwr的read_buffer,當bwr讀緩存有數據,則執行binder_thread_read;當讀失敗則再將bwr數據寫回用戶空間並退出;最後,把內核數據bwr拷貝到用戶空間ubuf。
12 binder_thread_write + binder_ioctl BR命令和數據傳遞
Server:
13 IPC.executeCommand 解析kernel傳過來的binder_transaction_data數據,找到目標BBinder並調用其transact()方法;
14 IPC.joinThreadPool 採用循環不斷地執行getAndExecuteCommand()方法, 處理事務。當bwr的讀寫buffer都沒有數據時,則阻塞在binder_thread_read的wait_event過程. 另外,正常情況下binder線程一旦創建則不會退出.
15 BBinder.transact 到Binder.exeTransact 調用 AMN.onTransact
16 AMN.onTransact 把數據傳遞到AMS.starService去執行
17 AMS.starService Server處理了Client的請求了
然後原路replay回去,talkWithDriver 到Kernel ,然後找到Client進程,把數據拷貝到read_buffer里,最終喚醒IPC,把反饋傳遞回AMP.startService。完成啟動服務。
3.2 從通信協議流程來看:
非oneWay:
oneway:
oneway與非oneway區別: 都是需要等待Binder Driver的回應消息BR_TRANSACTION_COMPLETE. 主要區別在於oneway的通信收到BR_TRANSACTION_COMPLETE則返回,而不會再等待BR_REPLY消息的到來. 另外,oneway的binder IPC則接收端無法獲取對方的pid.
3.3 從數據流來看
從用戶空間開始:
進入驅動後:
回到用戶空間:
參考:
http://gityuan.com/2016/09/04/binder-start-service/
http://gityuan.com/2015/11/28/binder-summary/
http://gityuan.com/2015/11/14/binder-add-service/
http://gityuan.com/2015/11/15/binder-get-service/
⑼ Android之Binder通信篇
Binder跨進程通信的本質是依賴內核驅動將屬於不同Binder進程的數據,從原始進程復制到目標進程,這樣就完成了跨進程通信了。
Binder通過獨特的內存映射機制,在跨進程通信時,可以做到一次拷貝,兩個空間同時使用!如下圖:
Binder跨進程通信是要傳遞數據的,既然有數據必然要佔用內存空間,Android系統規定每一個進程都有一塊Binder內存區,也就是圖1中的 共享內存 ,系統最多隻能給該區域分配4M的物理內存,由於申請這塊內存是通過系統的mmap函數完成的,所以整個映射機制又被稱為mmap機制
為了把這部分說明白,就再盜圖一張,命名圖2吧!
對於Binder驅動,通過 binder_procs 鏈表記錄所有創建的 binder_proc 結構體,binder 驅動層的每一個 binder_proc 結構體都與用戶空間的一個用於 binder 通信的進程一一對應,且每個進程有且只有一個 ProcessState 對象,這是通過單例模式來保證的。在每個進程中可以有很多個線程,每個線程對應一個 IPCThreadState 對象,IPCThreadState 對象也是單例模式,即一個線程對應一個 IPCThreadState 對象,在 Binder 驅動層也有與之相對應的結構,那就是 Binder_thread 結構體。在 binder_proc 結構體中通過成員變數 rb_root threads,來記錄當前進程內所有的 binder_thread。
Binder 線程池:每個 Server 進程在啟動時創建一個 binder 線程池,並向其中注冊一個 Binder 線程;之後 Server 進程也可以向 binder 線程池注冊新的線程,或者 Binder 驅動在探測到沒有空閑 binder 線程時主動向 Server 進程注冊新的的 binder 線程。對於一個 Server 進程有一個最大 Binder 線程數限制,默認為16個 binder 線程,例如 Android 的 system_server 進程就存在16個線程。對於所有 Client 端進程的 binder 請求都是交由 Server 端進程的 binder 線程來處理的。