在上一篇文章(為什么要學(xué)習(xí)) AsyncTask 原理 提到了線程池账月,那么現(xiàn)在來學(xué)習(xí)學(xué)習(xí) Android 的線程池澡刹。那么來看看線程池有什么優(yōu)點(diǎn)闲孤,或者說為什么要學(xué)習(xí)線程池。
- 重用線程池中的線程洞拨,避免了新建和銷毀線程的內(nèi)存開銷扯罐。
- 能有效線程池的最大并發(fā)數(shù),避免大量的線程之間因互相搶占系統(tǒng)資源而導(dǎo)致阻塞現(xiàn)象烦衣。
- 能夠?qū)€程進(jìn)行簡單的管理歹河,并提供定時(shí)執(zhí)行以及指定間隔循環(huán)執(zhí)行等功能。
基礎(chǔ)線程池
常用的線程池有挺多的花吟,首先來看看基礎(chǔ)線程池 ThreadPoolExcutor 秸歧,其他常見線程池都是基于 ThreadPoolExcutor 去實(shí)現(xiàn)的。那么我們先從它的構(gòu)造方法入手衅澈。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
參數(shù):corePoolSize
線程池的核心線程數(shù)键菱,默認(rèn)情況下核心線程會一直存在,即便是線程處于閑置狀態(tài)今布。
參數(shù):maximumPoolSize
線程池所能容納的最大線程數(shù)经备,當(dāng)核心線程不夠用時(shí)拭抬,就會開啟非核心線程來處理任務(wù),maximumPoolSize = corePoolSize + 非核心線程數(shù)
參數(shù):keepAliveTime
當(dāng)非核心線程處理完任務(wù)處于閑置閑置狀態(tài)時(shí)侵蒙,如果在一定時(shí)間范圍內(nèi)沒有被重用造虎,就會被銷毀。而 keepAliveTime 就是前面所指的一定時(shí)間范圍纷闺。
參數(shù):unit
有了時(shí)間范圍算凿,當(dāng)然要確定時(shí)間的單位。而這個(gè)參數(shù)就是描述時(shí)間范圍的參數(shù)急但。這是一個(gè)枚舉參數(shù)澎媒,常用的有:
TimeUnit.DAYS
TimeUnit.HOURS
TimeUnit.MINUTES
參數(shù):workQueue
線程池的任務(wù)隊(duì)列,線程池的 excute 方法提交的任務(wù)會進(jìn)入這個(gè)隊(duì)列波桩。
參數(shù):threadFactory
為線程池提供新建線程的方法--> newThread(Runnale r)
ThreadPoolExcutor 執(zhí)行任務(wù)時(shí)大致遵循的規(guī)則:
- 如果線程池中的線程數(shù)量還沒達(dá)到核心線程數(shù),則新開啟一個(gè)核心線程來執(zhí)行任務(wù)
- 如果已經(jīng)達(dá)到或者超過核心線程的數(shù)量请敦,則會被插入到任務(wù)隊(duì)列中镐躲,等待執(zhí)行
- 如果任務(wù)隊(duì)列已滿,則會新開啟一個(gè)非核心線程來執(zhí)行任務(wù)侍筛。
- 如果線程數(shù)達(dá)到最大值萤皂,則會拒絕執(zhí)行任務(wù)。
ok,解釋了那么多還不如來 實(shí)踐一下匣椰,下面看看小例子:
mExecutor = new ThreadPoolExecutor(3, 6, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));//初始化 mExecutor
fab.setOnClickListener(new View.OnClickListener() {//設(shè)置一個(gè)點(diǎn)擊事件
@Override
public void onClick(View view) {
num++;
mExecutor.execute(new MyRunnable(String.valueOf(num)));
Log.d(TAG, "隊(duì)列中等待執(zhí)行的任務(wù)數(shù): "+String.valueOf(mExecutor.getPoolSize()));
Log.d(TAG, "執(zhí)行完畢是數(shù)量: "+String.valueOf(mExecutor.getCompletedTaskCount()));
}
});
常用線程池
FixedThreadPool
這是一種只有核心線程的線程池裆熙,線程都不會被回收,而且意味著能更快地響應(yīng)任務(wù)禽笑,并且任務(wù)隊(duì)列也沒有大小限制入录。
FixedThreadPool 實(shí)例化方法:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
實(shí)例:
ExecutorService e = Executors.newFixedThreadPool(5);
e.execute(new MyRunnable(String.valueOf(num)));
CachedThreadPool
這是一種線程數(shù)不確定的線程池,由下面的實(shí)例化方法可以看出佳镜,核心線程為0僚稿,非核心線程為 Integer.MAX_VALUE ,這是一個(gè)很大的數(shù)蟀伸。超時(shí)策略為 60 秒蚀同。另外,SynchronousQueue 是一個(gè)無法存儲元素的隊(duì)列啊掏,也就是說蠢络,每當(dāng)有新任務(wù),就會立即開啟一個(gè)線程迟蜜。而如果全部任務(wù)都處理完成刹孔,線程池中也可能存在 0 個(gè)線程的情況。所以小泉,幾乎不占用任何系統(tǒng)資源芦疏。
CachedThreadPool 實(shí)例化方法:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
實(shí)例:
ExecutorService e2 = Executors.newCachedThreadPool();
e2.execute(new MyRunnable(String.valueOf(num)));
ScheduledThreadPool
從下面的實(shí)例化方法可以看出冕杠,這是一個(gè)核心線程固定,非核心線程很大很大的一個(gè)線程池酸茴。DEFAULT_KEEPALIVE_MILLIS = 10L分预,也就是說超時(shí)策略為 10 毫秒。
實(shí)例化方法:
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
實(shí)例:
ExecutorService e3 = Executors.newScheduledThreadPool(5);
e3.execute(new MyRunnable(String.valueOf(num)));
SingleThreadPool
從下面的實(shí)例化方法中薪捍,可以看出笼痹,這個(gè)線程池,只有一個(gè)核心線程酪穿。它存在的意義就是確保所有任務(wù)都在同一個(gè)線程執(zhí)行凳干,使得這些任務(wù)不需要處理線程同步的問題。
實(shí)例化方法:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
實(shí)例:
ExecutorService e4 = Executors.newSingleThreadExecutor();
e4.execute(new MyRunnable(String.valueOf(num)));
總結(jié)
進(jìn)過一系列的學(xué)習(xí)被济,對于線程池也是有了初步的了解救赐,但是了解歸了解,運(yùn)用到實(shí)際開發(fā)中優(yōu)勢另外一回事只磷。還得多與實(shí)際相結(jié)合经磅。
參考文獻(xiàn):《Android開發(fā)藝術(shù)探索》