第5章 Android進程/線程和程序內存優化
5.1 Android 進程和線程
進程(Process)是程序的一個運行實例,以區別於“程序”這一靜態的概念
而線程(Thread)則是CPU調度的基本單位。
實驗1 創建Activity
結論:啓動了3個線程:mainThread 和 2個Binder Thread
實驗2 創建Service
結論:Service也是寄存於 ActivityThread 中;啓動Service,同樣需要兩個Binder線程
實驗3 創建多個Activity(Service)
結論:主線程mainThread只有一個;Binder線程數量有所變化
實驗4 不同組件(除非特別聲明)運行在同一個進程中(並且均由主線程處理事件)
如果兩個對象處於同一進程空間中,那麼內存區域應該是可共享訪問的。
小結:
-
四大組件不是程序(進程)的全部,而只是它的“零件”
-
應用程序啓動後,將創建ActivityThread主線程
-
同一個包中的組件將運行在相同的進程空間中
-
不同包中的組件可以通過一定的方式運行在一個進程空間中
-
一個Activity應用啓動後至少會有3個線程:即1個主線程和2個Binder線程
5.2 Handler, MessageQueue, Runnable 與 Looper
Looper不斷獲取MessageQueue中的一個Message,然後由Handler來處理。
Thread和Handler是一對多的關係。
5.3 UI主線程——ActivityThread
ActivityThread是Activity所屬的線程,也就是UI主線程(自己理解:ActivityThread不是線程類,是管理主線程的類):
public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();//主Handler
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
消息是推動整個系統動起來的基礎。
5.4 Thread類
5.4.1 Thread的內部原理
Thread實現了Runnable, 也就是線程是“可執行的代碼”
使用Thread的方法:
1、繼承Thread,重寫它的run方法,然後調用:
MyThread thr = new MyThread(...);
thr.start();
2、直接實現Runnable
new Thread(Runnble target).start();
5.4.2 Thread 休眠和喚醒
- wait 和 notify/notifyAll
wait的解釋
Causes the calling thread to wait until another thread calls the notify() or notifyAll() method of this object.
- interrupt
wait是一種自願行爲,interrupt則是被迫的,如字面意思一樣,中斷線程的執行過程
- join
t1.start();
t1.join();
t2.start();
join的目的 只有當t1線程執行完成時,才執行後面的t2.start(),保證兩個線程的順序執行
- sleep
和wait一樣是自願的行爲,wait是等待某個object,sleep是等待時間。
5.5 Android應用程序如何利用CPU的多核處理能力
如何主動利用CPU的多核能力,提高自身的應用程序的性能?
答案是 針對Java-Based的並行編程技術
方式1:使用Java線程
方式2:使用AsyncTask
方式3:使用IntentService
5.6 Android應用程序的典型啓動流程
舊的Activity先onPause(),新的Activity再onResume()
5.7 Activity程序的內存管理與優化
5.7.1 系統對內存使用的限制
查看某個進程中的內存使用情況用 dumpsys命令,
dumpsys meminfo xxxPkg(或者pid)
Heap區域分Native(本地代碼的情況)、Dalvik(虛擬機中的堆分配)
5.7.2 Android中的內存泄漏和內存檢測
工具:Logcat、Memory Monitor、Heap Viewer、Allocation Tracker
定位問題的典型流程:用Memory Monitor觀察程序是否經常性發生GC(問題是否存在)—— 答案如果是肯定的,進一步用Heap Viewer來甄別可疑的對象類型(導致問題的可疑對象是什麼) —— 最後藉助於Allocation Tracker來確定發生問題的代碼在哪個位置(問題是如何產生的)
自己理解:現在Android Studio的Profile工具集成上面三步
內存泄漏檢測工具:Memory Analyzer Tool(MAT),用其Memory Leak Report