執行緒知識點總結
知識是什麼,知識就是看完了書把書扔掉之後腦中那些清晰、準確、必要的概念。
之前也寫了挺多關於執行緒的部落格,但是由於自己基礎不紮實,大多數都是摘錄別人的東西。所以這篇文章就是對一些重要的概念進行總結,把知識歸納整理,這篇部落格會長期更新,只要遇到了一些自己不懂而且重要的理論就會新增上去。
程序優先順序的5種類型:
前臺程序、可見程序、服務程序、後臺程序、空程序
1、前臺程序 (Foreground process)
一個正在與使用者互動的Activity
程序持有一個Service,這個Service處於這幾種狀態:
①Service與使用者正在互動的Activity繫結。
②Service是在前臺執行的,即它呼叫了 startForeground()。
③Service正在執行它的生命週期回撥函式(onCreate(), onStart(), or onDestroy())。
程序持有一個BroadcastReceiver,這個BroadcastReceiver正在執行它的 onReceive() 方法。
2、可見程序(Visible process)
程序持有一個Activity,這個Activity不在前臺,但是仍然被使用者可見(處於onPause()呼叫後又沒有呼叫onStop()的狀態,比如,前臺的activity打開了一個對話方塊,這樣activity就會在其後可見)。
程序持有一個Service,這個Service和一個可見的(或者前臺的)Activity繫結。
3、服務程序 (Service process)
如果一個程序中執行著一個service,這個service是通過 startService() 開啟的,並且不屬於上面兩種較高優先順序的情況,這個程序就是一個服務程序。
在Service中新啟動執行緒
上傳一個圖片檔案,應該開啟一個service來進行上傳工作,這樣在使用者離開activity時工作仍在進行
4、後臺程序 (Background process)
程序持有一個使用者不可見的activity(activity的onStop()被呼叫,但是onDestroy()沒有呼叫的狀態),就認為程序是一個後臺程序。
後臺播放音樂,後臺下載資料等
直接在Activity中新開一條執行緒來做耗時操作,當該Activity退出到桌面或其他情況
5、空程序
一個程序不包含任何活躍的應用元件
一個程序當中已經沒有資料在運行了,但是記憶體當中還為這個應用駐留了一個程序空間
如何提高Service優先順序
1、設定屬性priority最高優先順序,1000是最高值
2、在onStartCommand裡面呼叫 startForeground()方法把Service提升為前臺程序級別
3、onStartCommand方法,返回START_STICKY
public int onStartCommand(Intent intent, int flags, int startId) {
flags = START_STICKY;
returnsuper.onStartCommand(intent, flags, startId);
}
4、在onDestroy方法裡發廣播重啟service
5、監聽系統廣播判斷Service狀態
6、將該程序設定為常駐記憶體程序:在AndroidManifest的Application中新增android:persistent=”true”
開啟子執行緒的方式
Thread、AsyncTask、HandlerThread、IntentService、ThreadExecutor
1、Thread
簡單地開啟一個子執行緒進行處理,比如說處理一張圖片,讀取資原始檔,讀寫資料庫等。
要手動控制開啟和結束,不然會一直執行在後臺,即使程式退出
2、AsyncTask
適合與介面進行頻繁互動,比如說進度條,也可以做Thread可以做的事
3、HandlerThread
適合處理在前臺的多執行緒序列的程式
4、IntentService
適合處理在後臺執行的,多執行緒序列程式
5、ThreadExecutor
適合反覆多次使用執行緒的程式,比如說音樂下載,圖片載入(ImageLoader)
Thread
1、子執行緒建立Handler
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Handler handler = new Handler(Looper.myLooper()) {
@Override
public void handleMessage(Message msg) {
mTextView.setText("改變文字");
}
};
Looper.loop();
handler.sendEmptyMessage(123);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
AsyncTask
1、執行併發操作程式碼:
loadImageAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, path);
HandlerThread
IntentService
ThreadExecutor
execute和submit的區別
submit內部呼叫execute
submit有返回值
submit方便exception處理
Callable和Runnable的區別
Callable中的call()方法類似Runnable的run()方法,就是前者有返回值,後者沒有。
兩者都是為那些例項可能被另一個執行緒執行的類設計的。
但是 Runnable 不會返回結果,並且無法丟擲經過檢查的異常。
預設的執行緒池
newFixedThreadPool 固定數量
newSingleThreadExecutor 序列
newCachedThreadPool 無限大
newScheduledThreadPool 固定數量,週期性執行
BlockingQueue等待佇列
ArrayBlockingQueue:陣列結構的阻塞佇列
LinkedBlockingQueue:連結串列結構的阻塞佇列
PriorityBlockingQueue:有優先順序的阻塞佇列
SynchronousQueue:不會儲存元素的阻塞佇列
飽和策略
AbortPolicy : 預設的實現,直接丟擲一個RejectedExecutionException異常,讓呼叫者自己處理。
DiscardPolicy : 如果佇列滿了,後續的任務都拋棄掉。
DiscardOldestPolicy : 將等待佇列裡最舊的任務踢走,讓新任務得以執行。
CallerRunsPolicy : 既不拋棄新任務,也不拋棄舊任務,而是直接在當前執行緒執行這個任務。
ThreadFactory
每當執行緒池需要建立一個新執行緒,都是通過執行緒工廠獲取。如果不為ThreadPoolExecutor設定一個執行緒工廠,就會使用預設的defaultThreadFactory
平時列印執行緒池裡執行緒的name時,會輸出形如pool-1-thread-1之類的名稱,就是在這裡設定的。這個預設的執行緒工廠,建立的執行緒是普通的非守護執行緒,如果需要定製,實現ThreadFactory後傳給ThreadPoolExecutor即可。