
0. 前言
線程池概念,以前跟著 Android 視頻有學(xué)習(xí)過(guò),但沒(méi)有真正使用與梳理,間隔 時(shí)間較長(zhǎng)后,忘記的差不多。需要養(yǎng)成良性習(xí)慣,學(xué)習(xí)了新的知識(shí)點(diǎn)后需要梳理,轉(zhuǎn)換為自己理解語(yǔ)言使用技術(shù)文章描述,后續(xù)可以直接查閱筆記。
線程的創(chuàng)建與使用:
1. 線程池
線程池可以理解為同時(shí)管理多個(gè)線程,通過(guò) 線程重用,減少創(chuàng)建與銷毀對(duì)設(shè)備性能消耗,控制線程池中線程的并發(fā)數(shù),避免線程爭(zhēng)奪CPU資源造成阻塞,對(duì)線程進(jìn)行管理,達(dá)到軟件設(shè)計(jì)的需求;
2. 線程池基礎(chǔ)類「ThreadPoolExecutor 」
Execute 作為一個(gè)接口,具體實(shí)現(xiàn)類 ThreadPoolExecutor ;
Android中的線程池都是 直接或間接通過(guò)配置ThreadPoolExecutor 來(lái)實(shí)現(xiàn)不同特性的線程池
//核心線程數(shù),除非allowCoreThreadTimeOut被設(shè)置為true,否則它閑著也不會(huì)死
int corePoolSize,
//最大線程數(shù),活動(dòng)線程數(shù)量超過(guò)它,后續(xù)任務(wù)就會(huì)排隊(duì)
int maximumPoolSize,
//超時(shí)時(shí)長(zhǎng),作用于非核心線程(allowCoreThreadTimeOut被設(shè)置為true時(shí)也會(huì)同時(shí)作用于核心線程),閑置超時(shí)便被回收
long keepAliveTime,
//枚舉類型,設(shè)置keepAliveTime的單位,有TimeUnit.MILLISECONDS(ms)、TimeUnit. SECONDS(s)等
TimeUnit unit,
//緩沖任務(wù)隊(duì)列,線程池的execute方法會(huì)將Runnable對(duì)象存儲(chǔ)起來(lái)
BlockingQueue<Runnable> workQueue,
//線程工廠接口,只有一個(gè)new Thread(Runnable r)方法,可為線程池創(chuàng)建新線程
ThreadFactory threadFactory)
ThreadPoolExecutor的各個(gè)參數(shù)所代表的特性注釋中已經(jīng)寫的很清楚了,那么ThreadPoolExecutor執(zhí)行任務(wù)時(shí)的心路歷程是什么樣的呢?(以下用currentSize表示線程池中當(dāng)前線程數(shù)量)
(1) 當(dāng)currentSize<corePoolSize時(shí),直接啟動(dòng)一個(gè)核心線程并執(zhí)行任務(wù)。
(2) 當(dāng)currentSize>=corePoolSize、且workQueue未滿時(shí),添加進(jìn)來(lái)的任務(wù)會(huì)被安排到workQueue中等待執(zhí)行。
(3) 當(dāng)workQueue已滿,但是currentSize<maximumPoolSize時(shí),會(huì)立即開(kāi)啟一個(gè)非核心線程來(lái)執(zhí)行任務(wù)。
(4) 當(dāng)currentSize>=corePoolSize、workQueue已滿、并且currentSize>maximumPoolSize時(shí),調(diào)用handler默認(rèn)拋出RejectExecutionExpection異常。
3. Android 中常用的四類線程池
3.1 FixThreadPool「一堆人排隊(duì)上公廁」
* @param nThreads the number of threads in the pool
* @return the newly created thread pool
* @throws IllegalArgumentException if {@code nThreads <= 0}
*/
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
// 使用
Executors.newFixThreadPool(5).execute(Runnable);
(1)配置參數(shù),F(xiàn)ixThreadPool : 只有核心線程,數(shù)量固定,不會(huì)被回收,所有線程活動(dòng)是,應(yīng)為隊(duì)列沒(méi)有限制大小,新任務(wù)會(huì)等待執(zhí)行;
3.2 CachedThreadPool「一堆人去一家很大的咖啡館喝咖啡」
* @param threadFactory the factory to use when creating new threads
* @return the newly created thread pool
* @throws NullPointerException if threadFactory is null
*/
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}
// 使用
Executors.newCachedThreadPool().execute(Runnable);
(1)CachedThreadPool只有非核心線程,最大線程數(shù)非常大,所有線程都活動(dòng)時(shí),會(huì)為新任務(wù)創(chuàng)建新線程,否則利用空閑線程(60s空閑時(shí)間,過(guò)了就會(huì)被回收,所以線程池中有0個(gè)線程的可能)處理任務(wù)。
(2)任務(wù)隊(duì)列SynchronousQueue相當(dāng)于一個(gè)空集合,導(dǎo)致任何任務(wù)都會(huì)被立即執(zhí)行。
(3)【前方高能,筆者腦洞】CachedThreadPool就像是一堆人去一個(gè)很大的咖啡館喝咖啡,里面服務(wù)員也很多,隨時(shí)去,隨時(shí)都可以喝到咖啡。但是為了響應(yīng)國(guó)家的“光盤行動(dòng)”,一個(gè)人喝剩下的咖啡會(huì)被保留60秒,供新來(lái)的客人使用,哈哈哈哈哈,好惡心啊。如果你運(yùn)氣好,沒(méi)有剩下的咖啡,你會(huì)得到一杯新咖啡。但是以前客人剩下的咖啡超過(guò)60秒,就變質(zhì)了,會(huì)被服務(wù)員回收掉。
(4)比較適合執(zhí)行大量的耗時(shí)較少的任務(wù)。喝咖啡人挺多的,喝的時(shí)間也不長(zhǎng)。
3.3 SingleThreadPool「始終只有一個(gè)執(zhí)行線程」
* {@code newScheduledThreadPool(1)} the returned executor is
* guaranteed not to be reconfigurable to use additional threads.
* @return the newly created scheduled executor
*/
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1));
}
//使用
Executors.newSingleThreadPool ().execute(r);
3.4 ScheduledThreadPool「延遲執(zhí)行和周期重復(fù)執(zhí)行的線程池」
* @param corePoolSize the number of threads to keep in the pool,
* even if they are idle
* @return a newly created scheduled thread pool
* @throws IllegalArgumentException if {@code corePoolSize < 0}
*/
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
//使用,延遲1秒執(zhí)行,每隔2秒執(zhí)行一次Runnable r
Executors. newScheduledThreadPool (5).scheduleAtFixedRate(r, 1000, 2000, TimeUnit.MILLISECONDS);