Android 中的線程調度

ZZ:http://stackvoid.com/Thread-Scheduling-in-Android/

本文概述了 Android 中的線程是如何調度的,並通過設置線程優先級來優化 APP-UI,使其流暢運行。

線程調度聽起來很學術,是操作系統中的概念:線程調度決定系統中不同線程運行,運行時間,何時運行。Android 中的線程調度很操作系統中的線程調度類似,主要使用 nice 和 cgroups 這兩個變量來調度線程(本質上來說還是通過設置線程優先級,讓 Linux 內核有依據的分配線程運行)。

Nice


我們這裏的 Nice 與 Linux Kernel 的進程完全公平調度器(CFS)類似但是不一樣(本質上,在創建線程的時候這個 Nice 值最終還是要傳遞給底層的,跟 Linux Kernel 中的 nice 是相同的)。Java 層

Nice 在 Android 中是衡量線程優先級的重要參考指標;nice 值越大,線程優先級越低,反之越高;其中兩個重要的線程優先級屬性參數是,default 和 background , 對於 Android App,線程要做大量耗時工作,其優先級應該越低,否則系統有卡死的風險,反之,線程做的工作不多,應該設置其優先級較高。所以關於交互界面的線程(如 UI 線程等前臺線程)會給 default 或更高的優先級,而後臺線程(如執行 AsyncTask 的線程)的線程屬性爲background

Nice 這種特性可以讓後臺工作線程儘量少搶佔前臺線程的時間片(從OS來說),從而保證了用戶界面的流暢性。實際上,仍有一種可能使 UI 卡死,例如有30個後臺線程,但是隻有1個 UI 進程,這30個後臺線程可能佔據了很大的計算資源,導致 UI 線程得不到及時運行,導致卡頓、掉幀;爲了防止這種情況發生, Android 提出了 cgroups,用來解決類似的問題。

Cgroups


爲了解決上述問題,Android 將前臺線程和後臺線程分開運行,即利用Linux的 cgroups 給前臺線程建一個羣,給後臺線程建一個羣,然後調度器在這兩個羣中跑,這樣不管後臺線程有多少,調度器總能照顧到前臺線程的運行;所以用戶體驗得到了保證。

如何區分前臺進程和後臺進程的 cgroup?

Android 會自動將沒有在前臺進程 cgroup 運行的線程都放到後臺進程的 cgroup 中,這就保證了不管開多少線程,只會將其分爲兩個 Group,前臺 cgroup 和後臺 cgroup;理論上,不管多少非前臺線程運行,Android都能保證前臺線程的運行。

設置線程屬性


一般來說,Android API 將常用工作線程的優先級設置好了。例如,HandlerThread 的代碼第30行,將線程優先級設置爲Process.THREAD_PRIORITY_DEFAULTAsyncTask 代碼第286行,將線程優先級設置爲Process.THREAD_PRIORITY_BACKGROUND。再比如音樂播放的線程設置爲THREAD_PRIORITY_AUDIO,Android API 將常用情況都做了詳細的分類

需要銘記於心的是,在 UI 主線程實例化的線程或線程池,都會繼承 defaultforeground屬性(因爲 UI 線程就是這個屬性,子線程會繼承父線程的屬性),所以如果大量類似工作線程存在於前臺進程的 cgroup 中話,可能會使 UI 變得非常不流暢。若是工作線程,建議在運行前通過 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND) 直接設置線程的屬性。

1 new Thread(new Runnable() { 2 @Override 3 public void run() { 4 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 5 6 // ... 7 } 8 }).start();

發佈了23 篇原創文章 · 獲贊 0 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章