android 多執行緒程式設計
android 中的執行緒基於 linux 的執行緒,當我們啟動一個 App 的時候,Android系統會啟動一個Linux Process,該 Process 包含一個 Thread,稱為UI Thread或Main Thread。

android and linux
通過示例來了解 android 中的執行緒,建立一個新的 Android 專案。在 activity 中新增兩個 button (啟動和停止執行緒)和 textview,button 用於控制啟動和停止執行緒,textview用於接收執行緒返回值,便於檢視執行緒是如何更新檢視,後臺執行緒或叫做工作執行緒是如何與主執行緒進行通訊的。現在做一個最簡單的示例,程式碼如下。這裡列印的執行緒為主執行緒的 id。

圖1
執行一段時間,我們的應用就崩潰了,這是應列印阻塞了 UI 執行緒中其他邏輯的執行,從而導致介面卡頓。如果卡頓時間超過5秒,系統就會報 ANR 錯誤。這樣來看,要執行耗時的操作的話,我們就需要另起執行緒執行。

圖2
然後讓程式碼執行在一個新建立的執行緒,程式碼如下,再看一看效果,

圖5
好了!我們已經成功解決上一個問題,接下來要做的事。是如何把處理結果傳回到主執行緒以更新 UI。

圖6
我們通過 handler 物件,將在新執行緒中執行的結果傳送回主執行緒中來執行。


效果圖

handle
總結一下
Android 是如何處理執行緒間通訊的,看一看上圖,在主執行緒會迴圈地執行一個一個的任務。將 Message 或 Runnable 物件看成一個一個任務,這些物件(任務)線上程間傳遞資料。MessageQueque: 訊息佇列,是 Message 和 Runnable 的容器,他們都是按一定順序存放在訊息佇列中(任務可以按照一定優先順序進行執行),依次被處理 Looper :負責Message 和 Runnable 物件,分發給相應的 Handler 物件。Hander 即是 Message 和 Runnable 物件的來源,也就是說他將物件傳送給 MessageQueque 同時也是 Looper 物件的接收器,Looper 會把 Message 和 Runnable 傳送給 Handler。並且在從 Looper 接受後執行 Message 和 Runnable 傳送操作在傳送執行緒中完成,而執行操作在接收執行緒中完成,來實現不同執行緒的通訊。
AsyncTask是android提供的輕量級的非同步類,可以直接繼承AsyncTask,在類中實現非同步操作,並提供介面反饋當前非同步執行的程度(可以通過介面實現UI進度更新),最後反饋執行的結果給UI主執行緒。
AsyncTask 不是執行緒框架,只是一個用於工作執行緒和主執行緒之間通訊的通訊類。其中 doInBackground 是抽象方法,doPreExecute,onProgressUpdate, onPostExecute, onCancelled 還好理解,大家可以自己做些功課

圖7

圖8
這裡重點說一下 Executor 每次 AsyncTask 要被執行時,都必須提供一個 Executor 物件。啟動 AsyncTask 有三種方式
1. execute(params): 將任務新增到 SERIAL_EXECUTOR 佇列中。
2. execute(Runnable) 這是靜態方法,用於執行 Runnable 物件
3. executeOnExecutor(Executor, Params) 通過此方法可以指定 Executor。
AsyncTask通過一個阻塞佇列BlockingQuery<Runnable>儲存待執行的任務,利用靜態執行緒池THREAD_POOL_EXECUTOR提供一定數量的執行緒,預設128個。在Android 3.0以前,預設採取的是並行任務執行器,3.0以後改成了預設採用序列任務執行器,通過靜態序列任務執行器SERIAL_EXECUTOR控制任務序列執行,迴圈取出任務交給THREAD_POOL_EXECUTOR中的執行緒執行,執行完一個,再執行下一個。
可以嘗試自己來實現一個 looper 和 Handler。我們在 Thread.run() 中呼叫靜態方法 Looper.prepare() 來定義一個 Looper 物件,建立一個MessageQueue(訊息佇列),為了 Looper 分發 Message 和 Runnable 給 Handler。

圖9
建立一個執行緒,然後任務傳送到訊息佇列messageQueue

圖10
我們來將任務傳送給 Runnable 物件,工作程序中執行完的任務,返回到主執行緒中來更新 UI。

圖12
今天到這裡吧
