為什麼使用線程池?
1、重用線程,防止頻繁的建立銷毀線程所帶來的時間和資源等性能損耗。
2、有效的控制最大線程并發數,防止大量線程搶奪系統資源引起卡頓,合理利用系統資源。
3、對線程進行簡單管理、以及線程間更好的協作工作
Android 中有哪幾種線程池?
實際意義上我們所說的幾種常用線程池都是 Java 封裝好,都在 Executors 這個工廠類裡面了,筆者使用的是 JDK8 是以發現裡面有六種線程池,接下來分别介紹下
1. FixedThreadPool
數量固定的核心線程池,當線程池處于空閑時線程也不會被回收,除非線程被關閉了。如果所有線程都在運作中,再有新任務添加時新任務會處于等在狀态,知道有線程空閑在運作。處于等待的任務沒有數量上限
2. CachedThreadPool
這是一種線程數量不定的線程池,他隻有非核心線程,線程池如果沒有空閑線程,會随時建立新的線程來工作,如果空下來的線程空閑時長超過 60 秒,則會被回收。他在長時間不工作的時候内部是沒有任何線程的,也就是不消耗任何資源
3. SingleThreadExecutor
隻有一個核心線程的線程池,所有任務都要排隊等待由唯一的一個核心線程來處理,處于等待的任務隊列個數沒有上限
4. ScheduledThreadPool
這是一個核心線程數量固定,非核心線程沒有上限的線程池,非核心線程閑置時間超過 10 秒就會被回收(不同版本 JDK 可能不同),并且他的等待隊列隻有 16 個。并且支援定時及周期性任務執行。
5. SingleThreadScheduledExecutor
就是一個隻有一個核心線程的 ScheduledThreadPool 線程池
6. WorkStealingPool
建立持有足夠線程的線程池來支援給定的并行級别,并通過使用多個隊列,減少競争,它需要傳一個并行數量,如果不傳,則被設定為預設的CPU數量
自定義線程池
接下來上面提到的核心線程、非核心線程是什麼,還有上面線程池的實作。
上面所有的線程池都是通過以下兩個類建立的
一、 先說一說 ThreadPoolExecutor
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue,
Executors.defaultThreadFactory(),
defaultHandler);
}
看一看各項參數
- corePoolSize:線程池的核心線程數
- maximumPoolSize:線程池中允許的最大線程數(maximumPoolSize-corePoolSize = 非核心線程)
- keepAliveTime:空閑線程結束的逾時時間(如果 allowCoreThreadTimeOut 屬性設定為 true 核心線程閑置 keepAliveTime 時間以上也會被回收,false 則不會回收)
- unit:是一個枚舉,它表示的是 keepAliveTime 的機關
- workQueue:工作隊列,用于任務的存放
運作流程
- 線程池建立的時候裡面不會有任何線程
- 如果正在運作的線程數量小于 corePoolSize,那麼馬上建立線程運作這個任務;
- 如果正在運作的線程數量大于或等于 corePoolSize,那麼将這個任務放入隊列;
- 如果這時候隊列滿了,而且正在運作的線程數量小于 maximumPoolSize,那麼還是要建立非核心線程立刻運作這個任務;
- 如果隊列滿了,而且正在運作的線程數量大于或等于 maximumPoolSize,那麼線程池會抛出異常RejectExecutionException。
我們上面說的 FixedThreadPool、CachedThreadPool、SingleThreadExecutor、ScheduledThreadPool、SingleThreadScheduledExecutor 都是通過 ThreadPoolExecutor 建立的,好奇的人可以看一下源碼。
二、 ForkJoinPool
ForkJoinPool 是JDK 7加入的一個線程池類。Fork/Join 技術是分治算法(Divide-and-Conquer)的并行實作,它是一項可以獲得良好的并行性能的簡單且高效的設計技術。目的是為了幫助我們更好地利用多處理器帶來的好處,使用所有可用的運算能力來提升應用的性能。我們常用的數組工具類 Arrays 在JDK 8之後新增的并行排序方法(parallelSort)就運用了 ForkJoinPool 的特性,還有 ConcurrentHashMap 在JDK 8之後添加的函數式方法(如forEach等)也有運用。
我們上面說的 WorkStealingPool 都是通過 ForkJoinPool 建立的。
這個知識點比較複雜大家可以參考其他部落格