(1)在Java中默認狀況下一個進程只有一個線程,也就是主線程,其餘線程都是子線程,也叫工做線程。Android中的主線程主要處理和界面相關的事情,而子線程則每每用於執行耗時操做。線程的建立和銷燬的開銷較大,因此若是一個進程要頻繁地建立和銷燬線程的話,都會採用線程池的方式。
(2)在Android中除了Thread,還有HandlerThread
、AsyncTask
以及IntentService
等也都扮演着線程的角色,只是它們具備不一樣的特性和使用場景。AsyncTask封裝了線程池和Handler,它主要是爲了方便開發者在子線程中更新UI。HandlerThread是一種具備消息循環的線程,在它的內部可使用Handler。IntentService是一個服務,它內部採用HandlerThread來執行任務,當任務執行完畢後就會自動退出。由於它是服務的緣故,因此和後臺線程相比,它比較不容易被系統殺死。
(3)從Android 3.0開始,系統要求網絡訪問必須在子線程中進行,不然網絡訪問將會失敗並拋出NetworkOnMainThreadException
這個異常,這樣作是爲了不主線程因爲被耗時操做所阻塞從而出現ANR現象。
(4)AsyncTask是一個抽象泛型類,它提供了Params
、Progress
、Result
三個泛型參數,若是task確實不須要傳遞具體的參數,那麼均可以設置爲Void
。下面是它的四個核心方法,其中doInBackground
不是在主線程執行的。onPreExecute
、doInBackground
、onProgressUpdate
、onPostResult
android
(1)AsyncTask
的使用過程當中的條件限制:
1.AsyncTask的類必須在主線程中加載,這個過程在Android 4.1及以上版本中已經被系統自動完成。
2.AsyncTask對象必須在主線程中建立,execute
方法必須在UI線程中調用。
3.一個AsyncTask對象只能執行一次,即只能調用一次execute
方法,不然會報運行時異常。
4.在Android 1.6以前,AsyncTask是串行執行任務的,Android 1.6的時候AsyncTask開始採用線程池並行處理任務,可是從Android 3.0開始,爲了不AsyncTask帶來的併發錯誤,AsyncTask又採用一個線程來串行執行任務。儘管如此,在Android 3.0以及後續版本中,咱們可使用AsyncTask的executeOnExecutor
方法來並行執行任務。可是這個方法是Android 3.0新添加的方法,並不能在低版本上使用。
(2)AsyncTask的原理
1.AsyncTask中有兩個線程池:SerialExecutor
和THREAD_POOL_EXECUTOR
。前者是用於任務的排隊,默認是串行的線程池;後者用於真正執行任務。AsyncTask中還有一個Handler,即InternalHandler
,用於將執行環境從線程池切換到主線程。AsyncTask內部就是經過InternalHandler來發送任務執行的進度以及執行結束等消息。
2.AsyncTask排隊執行過程:系統先把參數Params
封裝爲FutureTask
對象,它至關於Runnable;接着將FutureTask交給SerialExecutor的execute
方法,它先把FutureTask插入到任務隊列tasks中,若是這個時候沒有正在活動的AsyncTask任務,那麼就會執行下一個AsyncTask任務,同時當一個AsyncTask任務執行完畢以後,AsyncTask會繼續執行其餘任務直到全部任務都被執行爲止。
(3)HandlerThread
就是一種可使用Handler的Thread,它的實現就是在run方法中經過Looper.prepare()
來建立消息隊列,並經過Looper.loop()
來開啓消息循環,這樣在實際的使用中就容許在HandlerThread中建立Handler了,外界能夠經過Handler的消息方式通知HandlerThread執行一個具體的任務。HandlerThread的run方法是一個無限循環,所以當明確不須要再使用HandlerThread的時候,能夠經過它的quit
或者quitSafely
方法來終止線程的執行。HandlerThread的最主要的應用場景就是用在IntentService中。
(4)IntentService
是一個繼承自Service的抽象類,要使用它就要建立它的子類。IntentService適合執行一些高優先級的後臺任務,這樣不容易被系統殺死。IntentService的onCreate
方法中會建立HandlerThread,並使用HandlerThread的Looper來構造一個Handler對象ServiceHandler,這樣經過ServiceHandler對象發送的消息最終都會在HandlerThread中執行。IntentService會將Intent封裝到Message中,經過ServiceHandler發送出去,在ServiceHandler的handleMessage
方法中會調用IntentService的抽象方法onHandleIntent
,因此IntentService的子類都要實現這個方法。網絡
(1)使用線程池的好處:
1.重用線程,避免線程的建立和銷燬帶來的性能開銷;
2.能有效控制線程池的最大併發數,避免大量的線程之間因互相搶佔系統資源而致使的阻塞現象;
3.可以對線程進行簡單的管理,並提供定時執行以及指定間隔循環執行等功能。
(2)Executor
只是一個接口,真正的線程池是ThreadPoolExecutor
。ThreadPoolExecutor提供了一系列參數來配置線程池,經過不一樣的參數能夠建立不一樣的線程池,Android的線程池都是經過Executors
提供的工廠方法獲得的。
(3)ThreadPoolExecutor的構造參數
1.corePoolSize
:核心線程數,默認狀況下,核心線程會在線程池中一直存活;
2.maximumPoolSize
:最大線程數,當活動線程數達到這個數值後,後續的任務將會被阻塞;
3.keepAliveTime
:非核心線程閒置時的超時時長,超過這個時長,閒置的非核心線程就會被回收;
4.unit
:用於指定keepAliveTime參數的時間單位,有TimeUnit.MILLISECONDS
、TimeUnit.SECONDS
、TimeUnit.MINUTES
等;
5.workQueue
:任務隊列,經過線程池的execute方法提交的Runnable對象會存儲在這個參數中;
6.threadFactory
:線程工廠,爲線程池提供建立新線程的功能。它是一個接口,它只有一個方法Thread newThread(Runnable r)
;
7.RejectedExecutionHandler
:當線程池沒法執行新任務時,多是因爲任務隊列已滿或者是沒法成功執行任務,這個時候就會調用這個Handler的rejectedExecution
方法來通知調用者,默認狀況下,rejectedExecution
會直接拋出一個rejectedExecutionException
。
(4)ThreadPoolExecutor執行任務的規則:
1.若是線程池中的線程數未達到核心線程的數量,那麼會直接啓動一個核心線程來執行任務;
2.若是線程池中的線程數量已經達到或者超過核心線程的數量,那麼任務會被插入到任務隊列中排隊等待執行;
3.若是在步驟2中沒法將任務插入到的任務隊列中,多是任務隊列已滿,這個時候若是線程數量沒有達到規定的最大值,那麼會馬上啓動非核心線程來執行這個任務;
4.若是步驟3中線程數量已經達到線程池規定的最大值,那麼就拒絕執行此任務,ThreadPoolExecutor會調用RejectedExecutionHandler
的rejectedExecution
方法來通知調用者。
(5)AsyncTask的THREAD_POOL_EXECUTOR線程池的配置:
1.corePoolSize
=CPU核心數+1;
2.maximumPoolSize
=2倍的CPU核心數+1;
3.核心線程無超時機制,非核心線程在閒置時間的超時時間爲1s
;
4.任務隊列的容量爲128
。
(6)Android中常見的4類具備不一樣功能特性的線程池:
1.FixedThreadPool
:線程數量固定的線程池,它只有核心線程;
2.CachedThreadPool
:線程數量不固定的線程池,它只有非核心線程;
3.ScheduledThreadPool
:核心線程數量固定,非核心線程數量沒有限制的線程池,主要用於執行定時任務和具備固定週期的任務;
4.SingleThreadPool
:只有一個核心線程的線程池,確保了全部的任務都在同一個線程中按順序執行。併發