真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

android線程通信,android線程間通信

Android通信方式篇(七)-Binder機(jī)制(Native層(下))

本篇文章針對(duì)向ServiceManager注冊(cè)服務(wù) 和 獲取服務(wù)兩個(gè)流程來(lái)做總結(jié)。在這兩個(gè)過(guò)程中,ServiceManager都扮演的是服務(wù)端,與客戶(hù)端之間的通信也是通過(guò)Binder IPC。

讓客戶(hù)滿(mǎn)意是我們工作的目標(biāo),不斷超越客戶(hù)的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶(hù),將通過(guò)不懈努力成為客戶(hù)在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:國(guó)際域名空間、網(wǎng)頁(yè)空間、營(yíng)銷(xiāo)軟件、網(wǎng)站建設(shè)、泰來(lái)網(wǎng)站維護(hù)、網(wǎng)站推廣。

在此之前先了解下Binder的進(jìn)程與線程的關(guān)系:

用戶(hù)空間 :ProcessState描述一個(gè)進(jìn)程,IPCThreadState對(duì)應(yīng)一個(gè)進(jìn)程中的一個(gè)線程。

內(nèi)核空間 :binder_proc描述一個(gè)進(jìn)程,統(tǒng)一由binder_procs全局鏈表保存,binder_thread對(duì)應(yīng)進(jìn)程的一個(gè)線程。

ProcessState與binder_proc是一一對(duì)應(yīng)的。

Binder線程池 :每個(gè)Server進(jìn)程在啟動(dòng)時(shí)會(huì)創(chuàng)建一個(gè)binder線程池,并向其中注冊(cè)一個(gè)Binder線程;之后Server進(jìn)程也可以向binder線程池注冊(cè)新的線程,或者Binder驅(qū)動(dòng)在探測(cè)到?jīng)]有空閑binder線程時(shí)會(huì)主動(dòng)向Server進(jìn)程注冊(cè)新的的binder線程。對(duì)于一個(gè)Server進(jìn)程有一個(gè)最大Binder線程數(shù)限制15,(#define DEFAULT_MAX_BINDER_THREADS 15)。對(duì)于所有Client端進(jìn)程的binder請(qǐng)求都是交由Server端進(jìn)程的binder線程來(lái)處理的。我的理解是:binder線程是進(jìn)程進(jìn)行binder ipc時(shí)的一條數(shù)據(jù)處理路徑。

MediaPlayerService向ServiceManager注冊(cè)過(guò)程如下:

相關(guān)類(lèi):

整個(gè)過(guò)程總結(jié)如下:

1 獲取BpServiceManager 與 BpBinder

由defaultServiceManager()返回的是BpServiceManager,同時(shí)會(huì)創(chuàng)建ProcessState對(duì)象和BpBinder對(duì)象。然后通過(guò)BpBinder執(zhí)行transact,把真正工作交給IPCThreadState來(lái)處理。

2 BpBinder transact

Binder代理類(lèi)調(diào)用transact()方法,真正工作還是交給IPCThreadState來(lái)進(jìn)行transact工作。

3 通過(guò)IPCThreadState 包裝并轉(zhuǎn)換數(shù)據(jù)并進(jìn)行transact事務(wù)處理

每個(gè)線程都有一個(gè)IPCThreadState,每個(gè)IPCThreadState中都有一對(duì)Parcel變量:mIn、mOut。相當(dāng)于兩根數(shù)據(jù)管道:

最后執(zhí)行talkWithDriver。

writeTransactionData:將BC Protocol + binder_transaction_data結(jié)構(gòu)體 寫(xiě)入mOut, 然后執(zhí)行waitForResponse:

由talkWithDriver將數(shù)據(jù)進(jìn)一步封裝到binder_write_read結(jié)構(gòu)體,通過(guò)ioctl(BINDER_WRITE_READ)與驅(qū)動(dòng)通信。同時(shí)等待驅(qū)動(dòng)返回的接收BR命令,從mIn取出返回的數(shù)據(jù)。

mIn包裝的數(shù)據(jù)結(jié)構(gòu)(注冊(cè)服務(wù)handle = 0 ,code 為ADD_SERVICE_TRANSACTION):

4 Binder Driver

把binder_write_read結(jié)構(gòu)體write_buffer里數(shù)據(jù)取出來(lái),分別得到BC命令和封裝好數(shù)據(jù)的事務(wù)binder_transaction_data, 然后根據(jù)handler,在當(dāng)前binder_proc中,找到相應(yīng)的binder_ref,由binder_ref再找到目標(biāo)binder_node實(shí)體,由目標(biāo)binder_node再找到目標(biāo)進(jìn)程binder_proc。然后就是插入數(shù)據(jù):當(dāng)binder驅(qū)動(dòng)可以找到合適的線程,就會(huì)把binder_transaction節(jié)點(diǎn)插入到servciemanager的線程的todo隊(duì)列中,如果找不到合適的線程,就把節(jié)點(diǎn)之間插入servciemanager的binder_proc的todo隊(duì)列。

5 ServiceManager

經(jīng)過(guò)Binder Driver的處理,數(shù)據(jù)已經(jīng)到了ServiceManager進(jìn)程,在BR_TRANSACTION的引導(dǎo)下,在binder_loop()中執(zhí)行binder_parser()取出數(shù)據(jù),執(zhí)行do_add_service()操作,最終向 svcinfo 列表中添加已經(jīng)注冊(cè)的服務(wù)(沒(méi)有數(shù)據(jù)的返回)。最后發(fā)送 BR_REPLY 命令喚醒等待的線程,通知注冊(cè)成功。結(jié)束MediaPlayerService進(jìn)程 waitForResponse()的狀態(tài),整個(gè)注冊(cè)過(guò)程結(jié)束。

獲取服務(wù)的過(guò)程與注冊(cè)類(lèi)似,首先 ServiceManager 向 Binder 驅(qū)動(dòng)發(fā)送 BC_TRANSACTION 命令攜帶 CHECK_SERVICE_TRANSACTION 命令,同時(shí)獲取服務(wù)的線程進(jìn)入等待狀態(tài) waitForResponse()。Binder 驅(qū)動(dòng)收到請(qǐng)求命令向 ServiceManager 的發(fā)送 BC_TRANSACTION 查詢(xún)已注冊(cè)的服務(wù),會(huì)區(qū)分請(qǐng)求服務(wù)所屬進(jìn)程情況。

查詢(xún)到直接響應(yīng) BR_REPLY 喚醒等待的線程。若查詢(xún)不到將與 binder_procs 鏈表中的服務(wù)進(jìn)行一次通訊再響應(yīng)。

以startService為例來(lái)簡(jiǎn)單總結(jié)下執(zhí)行流程:

3.1 從方法執(zhí)行流程來(lái)看:

Client :

1 AMP.startService 標(biāo)記方法以及通過(guò)Parcel包裝數(shù)據(jù);

2 BinderProxy.transact 實(shí)際調(diào)用native的 android_os_BinderProxy_transact 傳遞數(shù)據(jù);

3 獲取BpServiceManager 與 BpBinder 同時(shí)會(huì)創(chuàng)建ProcessState。然后通過(guò)BpBinder執(zhí)行transact,把真正工作交給IPCThreadState來(lái)處理;

4 IPC.transact 主要執(zhí)行writeTransactionData,將上層傳來(lái)的數(shù)據(jù)重新包裝成binder_transaction_data,并將BC Protocol + binder_transaction_data結(jié)構(gòu)體 寫(xiě)入mOut;

5 IPC waitForResponse talkWithDriver + 等待返回?cái)?shù)據(jù);

6 talkWithDriver 將數(shù)據(jù)進(jìn)一步封裝成binder_write_read,通過(guò)ioctl(BINDER_WRITE_READ)與驅(qū)動(dòng)通信;

Kernel :

7 binder ioctl 接收BINDER_WRITE_READ ioctl命令;

8 binder_ioctl_write_read 把用戶(hù)空間數(shù)據(jù)ubuf拷貝到內(nèi)核空間bwr;

9 binder_thread_write 當(dāng)bwr寫(xiě)緩存有數(shù)據(jù),則執(zhí)行binder_thread_write;當(dāng)寫(xiě)失敗則將bwr數(shù)據(jù)寫(xiě)回用戶(hù)空間并退出;

10 binder_transaction 找到目標(biāo)進(jìn)程binder_proc并插入數(shù)據(jù)到目標(biāo)進(jìn)程的線程todo隊(duì)列,最終執(zhí)行到它

時(shí),將發(fā)起端數(shù)據(jù)拷貝到接收端進(jìn)程的buffer結(jié)構(gòu)體;

11 binder_thread_read 根據(jù)binder_transaction結(jié)構(gòu)體和binder_buffer結(jié)構(gòu)體數(shù)據(jù)生成新的binder_transaction_data結(jié)構(gòu)體,寫(xiě)入bwr的read_buffer,當(dāng)bwr讀緩存有數(shù)據(jù),則執(zhí)行binder_thread_read;當(dāng)讀失敗則再將bwr數(shù)據(jù)寫(xiě)回用戶(hù)空間并退出;最后,把內(nèi)核數(shù)據(jù)bwr拷貝到用戶(hù)空間ubuf。

12 binder_thread_write + binder_ioctl BR命令和數(shù)據(jù)傳遞

Server:

13 IPC.executeCommand 解析kernel傳過(guò)來(lái)的binder_transaction_data數(shù)據(jù),找到目標(biāo)BBinder并調(diào)用其transact()方法;

14 IPC.joinThreadPool 采用循環(huán)不斷地執(zhí)行g(shù)etAndExecuteCommand()方法, 處理事務(wù)。當(dāng)bwr的讀寫(xiě)buffer都沒(méi)有數(shù)據(jù)時(shí),則阻塞在binder_thread_read的wait_event過(guò)程. 另外,正常情況下binder線程一旦創(chuàng)建則不會(huì)退出.

15 BBinder.transact 到Binder.exeTransact 調(diào)用 AMN.onTransact

16 AMN.onTransact 把數(shù)據(jù)傳遞到AMS.starService去執(zhí)行

17 AMS.starService Server處理了Client的請(qǐng)求了

然后原路replay回去,talkWithDriver 到Kernel ,然后找到Client進(jìn)程,把數(shù)據(jù)拷貝到read_buffer里,最終喚醒IPC,把反饋傳遞回AMP.startService。完成啟動(dòng)服務(wù)。

3.2 從通信協(xié)議流程來(lái)看:

非oneWay:

oneway:

oneway與非oneway區(qū)別: 都是需要等待Binder Driver的回應(yīng)消息BR_TRANSACTION_COMPLETE. 主要區(qū)別在于oneway的通信收到BR_TRANSACTION_COMPLETE則返回,而不會(huì)再等待BR_REPLY消息的到來(lái). 另外,oneway的binder IPC則接收端無(wú)法獲取對(duì)方的pid.

3.3 從數(shù)據(jù)流來(lái)看

從用戶(hù)空間開(kāi)始:

進(jìn)入驅(qū)動(dòng)后:

回到用戶(hù)空間:

參考:

Android進(jìn)程間和線程間通信方式

? 進(jìn)程:是具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合上的一次運(yùn)行活動(dòng),進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位。

??線程:是進(jìn)程的一個(gè)實(shí)體,是CPU調(diào)度和分派的基本單位,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位。線程自己基本上不擁有系統(tǒng)資源,只擁有一些在運(yùn)行中必不可少的資源(如程序計(jì)數(shù)器,一組寄存器和棧),但是它可與同屬一個(gè)進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源。

??區(qū)別:

??(1)、一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程;

??(2)、線程的劃分尺度小于進(jìn)程,使得多線程程序的并發(fā)性高;

??(3)、進(jìn)程在執(zhí)行過(guò)程中擁有獨(dú)立的內(nèi)存單元,而多個(gè)線程共享內(nèi)存,但線程之間沒(méi)有單獨(dú)的地址空間,一個(gè)線程死掉就等于整個(gè)進(jìn)程死掉。

---------------------

一、Android進(jìn)程間通信方式

1.Bundle

??由于Activity,Service,Receiver都是可以通過(guò)Intent來(lái)攜帶Bundle傳輸數(shù)據(jù)的,所以我們可以在一個(gè)進(jìn)程中通過(guò)Intent將攜帶數(shù)據(jù)的Bundle發(fā)送到另一個(gè)進(jìn)程的組件。

??缺點(diǎn):無(wú)法傳輸Bundle不支持的數(shù)據(jù)類(lèi)型。

2.ContentProvider

??ContentProvider是Android四大組件之一,以表格的方式來(lái)儲(chǔ)存數(shù)據(jù),提供給外界,即Content Provider可以跨進(jìn)程訪問(wèn)其他應(yīng)用程序中的數(shù)據(jù)。用法是繼承ContentProvider,實(shí)現(xiàn)onCreate,query,update,insert,delete和getType方法,onCreate是負(fù)責(zé)創(chuàng)建時(shí)做一些初始化的工作,增刪查改的方法就是對(duì)數(shù)據(jù)的查詢(xún)和修改,getType是返回一個(gè)String,表示Uri請(qǐng)求的類(lèi)型。注冊(cè)完后就可以使用ContentResolver去請(qǐng)求指定的Uri。

3.文件

??兩個(gè)進(jìn)程可以到同一個(gè)文件去交換數(shù)據(jù),我們不僅可以保存文本文件,還可以將對(duì)象持久化到文件,從另一個(gè)文件恢復(fù)。要注意的是,當(dāng)并發(fā)讀/寫(xiě)時(shí)可能會(huì)出現(xiàn)并發(fā)的問(wèn)題。

4.Broadcast

??Broadcast可以向android系統(tǒng)中所有應(yīng)用程序發(fā)送廣播,而需要跨進(jìn)程通訊的應(yīng)用程序可以監(jiān)聽(tīng)這些廣播。

5.AIDL方式

??Service和Content Provider類(lèi)似,也可以訪問(wèn)其他應(yīng)用程序中的數(shù)據(jù),Content Provider返回的是Cursor對(duì)象,而Service返回的是Java對(duì)象,這種可以跨進(jìn)程通訊的服務(wù)叫AIDL服務(wù)。

? ? ?AIDL通過(guò)定義服務(wù)端暴露的接口,以提供給客戶(hù)端來(lái)調(diào)用,AIDL使服務(wù)器可以并行處理,而Messenger封裝了AIDL之后只能串行運(yùn)行,所以Messenger一般用作消息傳遞。

6.Messenger

??Messenger是基于AIDL實(shí)現(xiàn)的,服務(wù)端(被動(dòng)方)提供一個(gè)Service來(lái)處理客戶(hù)端(主動(dòng)方)連接,維護(hù)一個(gè)Handler來(lái)創(chuàng)建Messenger,在onBind時(shí)返回Messenger的binder。

??雙方用Messenger來(lái)發(fā)送數(shù)據(jù),用Handler來(lái)處理數(shù)據(jù)。Messenger處理數(shù)據(jù)依靠Handler,所以是串行的,也就是說(shuō),Handler接到多個(gè)message時(shí),就要排隊(duì)依次處理。

7.Socket

??Socket方法是通過(guò)網(wǎng)絡(luò)來(lái)進(jìn)行數(shù)據(jù)交換,注意的是要在子線程請(qǐng)求,不然會(huì)堵塞主線程??蛻?hù)端和服務(wù)端建立連接之后即可不斷傳輸數(shù)據(jù),比較適合實(shí)時(shí)的數(shù)據(jù)傳輸

二、Android線程間通信方式

??一般說(shuō)線程間通信主要是指主線程(也叫UI線程)和子線程之間的通信,主要有以下兩種方式:

1.AsyncTask機(jī)制

??AsyncTask,異步任務(wù),也就是說(shuō)在UI線程運(yùn)行的時(shí)候,可以在后臺(tái)的執(zhí)行一些異步的操作;AsyncTask可以很容易且正確地使用UI線程,AsyncTask允許進(jìn)行后臺(tái)操作,并在不顯示使用工作線程或Handler機(jī)制的情況下,將結(jié)果反饋給UI線程。但是AsyncTask只能用于短時(shí)間的操作(最多幾秒就應(yīng)該結(jié)束的操作),如果需要長(zhǎng)時(shí)間運(yùn)行在后臺(tái),就不適合使用AsyncTask了,只能去使用Java提供的其他API來(lái)實(shí)現(xiàn)。

2.Handler機(jī)制

??Handler,繼承自O(shè)bject類(lèi),用來(lái)發(fā)送和處理Message對(duì)象或Runnable對(duì)象;Handler在創(chuàng)建時(shí)會(huì)與當(dāng)前所在的線程的Looper對(duì)象相關(guān)聯(lián)(如果當(dāng)前線程的Looper為空或不存在,則會(huì)拋出異常,此時(shí)需要在線程中主動(dòng)調(diào)用Looper.prepare()來(lái)創(chuàng)建一個(gè)Looper對(duì)象)。使用Handler的主要作用就是在后面的過(guò)程中發(fā)送和處理Message對(duì)象和讓其他的線程完成某一個(gè)動(dòng)作(如在工作線程中通過(guò)Handler對(duì)象發(fā)送一個(gè)Message對(duì)象,讓UI線程進(jìn)行UI的更新,然后UI線程就會(huì)在MessageQueue中得到這個(gè)Message對(duì)象(取出Message對(duì)象是由其相關(guān)聯(lián)的Looper對(duì)象完成的),并作出相應(yīng)的響應(yīng))。

三、Android兩個(gè)子線程之間通信

??面試的過(guò)程中,有些面試官可能會(huì)問(wèn)Android子線程之間的通信方式,由于絕大部分程序員主要關(guān)注的是Android主線程和子線程之間的通信,所以這個(gè)問(wèn)題很容易讓人懵逼。

??主線程和子線程之間的通信可以通過(guò)主線程中的handler把子線程中的message發(fā)給主線程中的looper,或者,主線程中的handler通過(guò)post向looper中發(fā)送一個(gè)runnable。但looper默認(rèn)存在于main線程中,子線程中沒(méi)有Looper,該怎么辦呢?其實(shí)原理很簡(jiǎn)單,把looper綁定到子線程中,并且創(chuàng)建一個(gè)handler。在另一個(gè)線程中通過(guò)這個(gè)handler發(fā)送消息,就可以實(shí)現(xiàn)子線程之間的通信了。

??子線程創(chuàng)建handler的兩種方式:

??方式一:給子線程創(chuàng)建Looper對(duì)象:

new Thread(new Runnable() {

? ? ? ? public void run() {?

? ? ? ? ? ? Looper.prepare();? // 給這個(gè)Thread創(chuàng)建Looper對(duì)象,一個(gè)Thead只有一個(gè)Looper對(duì)象

? ? ? ? ? ? Handler handler = new Handler(){?

? ? ? ? ? ? ? ? @Override?

? ? ? ? ? ? ? ? public void handleMessage(Message msg) {?

? ? ? ? ? ? ? ? ? ? Toast.makeText(getApplicationContext(), "handleMessage", Toast.LENGTH_LONG).show();?

? ? ? ? ? ? ? ? }?

? ? ? ? ? ? };?

? ? ? ? ? ? handler.sendEmptyMessage(1);?

? ? ? ? ? ? Looper.loop(); // 不斷遍歷MessageQueue中是否有消息

? ? ? ? };?

? ? }).start();

---------------------

? ?方式二:獲取主線程的looper,或者說(shuō)是UI線程的looper:

new Thread(new Runnable() {

? ? ? ? public void run() {?

? ? ? ? ? ? Handler handler = new Handler(Looper.getMainLooper()){ // 區(qū)別在這!??!?

? ? ? ? ? ? ? ? @Override?

? ? ? ? ? ? ? ? public void handleMessage(Message msg) {?

? ? ? ? ? ? ? ? ? ? Toast.makeText(getApplicationContext(), "handleMessage", Toast.LENGTH_LONG).show();?

? ? ? ? ? ? ? ? }?

? ? ? ? ? ? };?

? ? ? ? ? ? handler.sendEmptyMessage(1);?

? ? ? ? };?

? ? }).start();

---------------------

Android多線程的四種方式:Handler、AsyncTask、ThreadPoolExector、IntentService

異步通信機(jī)制,將工作線程中需更新UI的操作信息 傳遞到 UI主線程,從而實(shí)現(xiàn) 工作線程對(duì)UI的更新處理,最終實(shí)現(xiàn)異步消息的處理。Handler不僅僅能將子線程的數(shù)據(jù)傳遞給主線程,它能實(shí)現(xiàn)任意兩個(gè)線程的數(shù)據(jù)傳遞。

(1)Message

Message 可以在線程之間傳遞消息。可以在它的內(nèi)部攜帶少量數(shù)據(jù),用于在不同線程之間進(jìn)行數(shù)據(jù)交換。除了 what 字段,還可以使用 arg1 和 arg2 來(lái)攜帶整型數(shù)據(jù),使用 obj 來(lái)攜帶 Object 數(shù)據(jù)。

(2) Handler

Handler 作為處理中心,用于發(fā)送(sendMessage 系列方法)與處理消息(handleMessage 方法)。

(3) MessageQueue

MessageQueue 用于存放所有通過(guò) Handler 發(fā)送的消息。這部分消息會(huì)一直存放在消息隊(duì)列中,直到被處理。每個(gè)線程中只會(huì)有一個(gè) MessageQueue 對(duì)象

(4) Looper

Looper 用于管理 MessageQueue 隊(duì)列,Looper對(duì)象通過(guò)loop()方法開(kāi)啟了一個(gè)死循環(huán)——for (;;){},不斷地從looper內(nèi)的MessageQueue中取出Message,并傳遞到 Handler 的 handleMessage() 方法中。每個(gè)線程中只會(huì)有一個(gè) Looper 對(duì)象。

AsyncTask 是一種輕量級(jí)的任務(wù)異步類(lèi),可以在后臺(tái)子線程執(zhí)行任務(wù),且將執(zhí)行進(jìn)度及執(zhí)行結(jié)果傳遞給 UI 線程。

(1)onPreExecute()

在 UI 線程上工作,在任務(wù)執(zhí)行 doInBackground() 之前調(diào)用。此步驟通常用于設(shè)置任務(wù),例如在用戶(hù)界面中顯示進(jìn)度條。

(2)doInBackground(Params... params)

在子線程中工作,在 onPreExecute() 方法結(jié)束后執(zhí)行,這一步被用于在后臺(tái)執(zhí)行長(zhǎng)時(shí)間的任務(wù),Params 參數(shù)通過(guò) execute(Params) 方法被傳遞到此方法中。任務(wù)執(zhí)行結(jié)束后,將結(jié)果傳遞給 onPostExecute(Result) 方法,同時(shí)我們可以通過(guò) publishProgress(Progress) 方法,將執(zhí)行進(jìn)度發(fā)送給 onProgressUpdate(Progress) 方法。

(3)onProgressUpdate(Progress... values)

在 UI 線程上工作,會(huì)在 doInBackground() 中調(diào)用 publishProgress(Progress) 方法后執(zhí)行,此方法用于在后臺(tái)計(jì)算仍在執(zhí)行時(shí)(也就是 doInBackgound() 還在執(zhí)行時(shí))將計(jì)算執(zhí)行進(jìn)度通過(guò) UI 顯示出來(lái)。例如,可以通過(guò)動(dòng)畫(huà)進(jìn)度條或顯示文本字段中的日志,從而方便用戶(hù)知道后臺(tái)任務(wù)執(zhí)行的進(jìn)度。

(4)onPostExecute(Result result)

在 UI 線程上工作,在任務(wù)執(zhí)行完畢(即 doInBackground(Result) 執(zhí)行完畢)并將執(zhí)行結(jié)果傳過(guò)來(lái)的時(shí)候工作。

使用規(guī)則:

(1)AsyncTask 是個(gè)抽象類(lèi),所以要?jiǎng)?chuàng)建它的子類(lèi)實(shí)現(xiàn)抽象方法

(1)AsyncTask 類(lèi)必須是在 UI 線程中被加載,但在Android 4.1(API 16)開(kāi)始,就能被自動(dòng)加載完成。

(2)AsyncTask 類(lèi)的實(shí)例對(duì)象必須在 UI 線程中被創(chuàng)建。

(3)execute() 方法必須是在 UI 線程中被調(diào)用。

(4)不要手動(dòng)調(diào)用方法 onPreExecute()、onPostExecute()、doInBackground()、onProgressUpdate()

(5)任務(wù)只能執(zhí)行一次(如果嘗試第二次執(zhí)行,將拋出異常)。即一個(gè)AsyncTask對(duì)象只能調(diào)用一次execute()方法。

原理:

? ? ? 其源碼中原理還是 Thread 與 Handler 的實(shí)現(xiàn),其包含 兩個(gè)線程池,一個(gè) Handler,如下所示:

名稱(chēng)類(lèi)型作用

SERIAL_EXECUTOR線程池分發(fā)任務(wù),串行分發(fā),一次只分發(fā)一個(gè)任務(wù)

THREAD_POOL_EXECUTOR線程池執(zhí)行任務(wù),并行執(zhí)行,執(zhí)行的任務(wù)由 SERIAL_EXECUTOR 分發(fā)

InternalHandlerHandler負(fù)責(zé)子線程與主線程的溝通,通知主線程做 UI 工作

一方面減少了每個(gè)并行任務(wù)獨(dú)自建立線程的開(kāi)銷(xiāo),另一方面可以管理多個(gè)并發(fā)線程的公共資源,從而提高了多線程的效率。所以ThreadPoolExecutor比較適合一組任務(wù)的執(zhí)行。Executors利用工廠模式對(duì)ThreadPoolExecutor進(jìn)行了封裝。

Executors提供了四種創(chuàng)建ExecutorService的方法,他們的使用場(chǎng)景如下:

1. Executors.newFixedThreadPool()

創(chuàng)建一個(gè)定長(zhǎng)的線程池,每提交一個(gè)任務(wù)就創(chuàng)建一個(gè)線程,直到達(dá)到池的最大長(zhǎng)度,這時(shí)線程池會(huì)保持長(zhǎng)度不再變化。

當(dāng)線程處于空閑狀態(tài)時(shí),它們并不會(huì)被回收,除非線程池被關(guān)閉。當(dāng)所有的線程都處于活動(dòng)狀態(tài)時(shí),新任務(wù)都會(huì)處于等待狀態(tài),直到有線程空閑出來(lái)。

只有核心線程并且不會(huì)被回收,能夠更加快速的響應(yīng)外界的請(qǐng)求。

2. Executors.newCachedThreadPool()

創(chuàng)建一個(gè)可緩存的線程池,如果當(dāng)前線程池的長(zhǎng)度超過(guò)了處理的需要時(shí),它可以靈活的回收空閑的線程,當(dāng)需要增加時(shí),它可以靈活的添加新的線程,而不會(huì)對(duì)池的長(zhǎng)度作任何限制

線程數(shù)量不定的線程池,只有非核心線程,最大線程數(shù)為 Integer.MAX_VALUE。當(dāng)線程池中的線程都處于活動(dòng)狀態(tài)時(shí),線程池會(huì)創(chuàng)建新的線程來(lái)處理新任務(wù),否則利用空閑的線程來(lái)處理新任務(wù)。線程池中的空閑線程具有超時(shí)機(jī)制,為 60s。

任務(wù)隊(duì)列相當(dāng)于一個(gè)空集合,導(dǎo)致任何任務(wù)都會(huì)立即被執(zhí)行,適合執(zhí)行大量耗時(shí)較少的任務(wù)。當(dāng)整個(gè)線程池都處于限制狀態(tài)時(shí),線程池中的線程都會(huì)超時(shí)而被停止。

3. Executors.newScheduledThreadPool()

創(chuàng)建一個(gè)定長(zhǎng)的線程池,而且支持定時(shí)的以及周期性的任務(wù)執(zhí)行,類(lèi)似于Timer。

非核心線程數(shù)沒(méi)有限制,并且非核心線程閑置的時(shí)候立即回收,主要用于執(zhí)行定時(shí)任務(wù)和具有固定周期的重復(fù)任務(wù)。

4. Executors.newSingleThreadExecutor()

創(chuàng)建一個(gè)單線程化的executor,它只創(chuàng)建唯一的worker線程來(lái)執(zhí)行任務(wù)

只有一個(gè)核心線程,保證所有的任務(wù)都在一個(gè)線程中順序執(zhí)行,意義在于不需要處理線程同步的問(wèn)題。

一般用于執(zhí)行后臺(tái)耗時(shí)任務(wù),當(dāng)任務(wù)執(zhí)行完成會(huì)自動(dòng)停止;同時(shí)由于它是一個(gè)服務(wù),優(yōu)先級(jí)要遠(yuǎn)遠(yuǎn)高于線程,更不容易被系統(tǒng)殺死,因此比較適合執(zhí)行一些高優(yōu)先級(jí)的后臺(tái)任務(wù)。

使用步驟:創(chuàng)建IntentService的子類(lèi),重寫(xiě)onHandleIntent方法,在onHandleIntent中執(zhí)行耗時(shí)任務(wù)

原理:在源碼實(shí)現(xiàn)上,IntentService封裝了HandlerThread和Handler。onHandleIntent方法結(jié)束后會(huì)調(diào)用IntentService的stopSelf(int startId)方法嘗試停止服務(wù)。

IntentService的內(nèi)部是通過(guò)消息的方式請(qǐng)求HandlerThread執(zhí)行任務(wù),HandlerThread內(nèi)部又是一種使用Handler的Thread,這就意味著IntentService和Looper一樣是順序執(zhí)行后臺(tái)任務(wù)的

(HandlerThread:封裝了Handler + ThreadHandlerThread適合在有需要一個(gè)工作線程(非UI線程)+任務(wù)的等待隊(duì)列的形式,優(yōu)點(diǎn)是不會(huì)有堵塞,減少了對(duì)性能的消耗,缺點(diǎn)是不能同時(shí)進(jìn)行多個(gè)任務(wù)的處理,需要等待進(jìn)行處理。處理效率低,可以當(dāng)成一個(gè)輕量級(jí)的線程池來(lái)用)


新聞標(biāo)題:android線程通信,android線程間通信
轉(zhuǎn)載注明:http://www.weahome.cn/article/dsdssps.html

其他資訊

在線咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部