背景
之前寫了兩篇關(guān)于線程和多線程的文章烟很,竟然寫到了多線程,那肯定少不了線程池啊蜓耻,如果想了解線程和線程池方面的知識可以查看我之前寫的
線程你真的了解它嗎
這才是真正的多線程
那么什么是線程池茫舶,它有什么優(yōu)點(diǎn)呢?
- 重用線程池中的線程刹淌,避免因?yàn)榫€程的創(chuàng)建和銷毀所帶來的性能開銷饶氏。
能有效控制線程池的最大并發(fā)數(shù),避免大量的線程之間因相互搶占系統(tǒng)資源而導(dǎo)致的堵塞線程有勾。 - 能夠?qū)€程進(jìn)行簡單的管理疹启,并提供定時執(zhí)行以及指定間隔循環(huán)執(zhí)行等功能。
- 相對于AsyncTask來說蔼卡,最大的優(yōu)勢在于:線程可控喊崖!比如在離開了某個頁面,提交到AsyncTask不能的任務(wù)不能撤銷雇逞,線程池可以在不需要的時候?qū)⒛硞€線程移除荤懂。
什么是線程池
那么線程池我們該怎么創(chuàng)建呢?首先我們先來看一下創(chuàng)建線程池的構(gòu)造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
我們先來看一下每一個參數(shù)的意義吧喝峦。
corePoolSize:核心池的大小势誊,在創(chuàng)建了線程池后,默認(rèn)情況下谣蠢,線程池中并沒有任何線程粟耻,而是等待有任務(wù)到來才創(chuàng)建線程去執(zhí)行任務(wù)查近,當(dāng)線程池中的線程數(shù)目達(dá)到corePoolSize后,就會把到達(dá)的任務(wù)放到緩存隊(duì)列當(dāng)中挤忙。只有當(dāng)工作隊(duì)列滿了的情況下才會創(chuàng)建超出這個數(shù)量的線程霜威。如果某個線程的空閑時間超過了活動時間,那么將標(biāo)記為可回收册烈,并且只有當(dāng)線程池的當(dāng)前大小超過corePoolSize時該線程才會被終止戈泼。用戶可調(diào)用prestartAllCoreThreads()或者prestartCoreThread()方法預(yù)先創(chuàng)建線程,即在沒有任務(wù)到來之前就創(chuàng)建corePoolSize個線程或者一個線程赏僧。
maximumPoolSize:線程池最大線程數(shù)大猛,這個參數(shù)也是一個非常重要的參數(shù),它表示在線程池中最多能創(chuàng)建多少個線程淀零;當(dāng)大于了這個值就會將Thread由一個丟棄處理機(jī)制來處理挽绩。
keepAliveTime:表示線程沒有任務(wù)執(zhí)行時最多保持多久時間會終止。默認(rèn)情況下驾中,只有當(dāng)線程池中的線程數(shù)大于corePoolSize時唉堪,keepAliveTime才會起作用,直到線程池中的線程數(shù)不大于corePoolSize肩民,即當(dāng)線程池中的線程數(shù)大于corePoolSize時唠亚,如果一個線程空閑的時間達(dá)到keepAliveTime,則會終止持痰,直到線程池中的線程數(shù)不超過corePoolSize灶搜。但是如果調(diào)用了allowCoreThreadTimeOut(boolean)方法,在線程池中的線程數(shù)不大于corePoolSize時共啃,keepAliveTime參數(shù)也會起作用蝗罗,直到線程池中的線程數(shù)為0逾礁;
Unit:參數(shù)keepAliveTime的時間單位,有7種取值,在TimeUnit類中有7種靜態(tài)屬性披粟。
workQueue:一個阻塞隊(duì)列镊靴,用來存儲等待執(zhí)行的任務(wù)盾致,當(dāng)線程池中的線程數(shù)目達(dá)到corePoolSize后照弥,就會把到達(dá)的任務(wù)放到緩存隊(duì)列當(dāng)中。
threadFactory:線程工廠攻人,主要用來創(chuàng)建線程取试;
handler:表示當(dāng)拒絕處理任務(wù)時的策略,也就是參數(shù)maximumPoolSize達(dá)到后丟棄處理的方法怀吻。有以下四種取值:
ThreadPoolExecutor.AbortPolicy:丟棄任務(wù)并拋出RejectedExecutionException異常瞬浓。
ThreadPoolExecutor.DiscardPolicy:也是丟棄任務(wù),但是不拋出異常蓬坡。
ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊(duì)列最前面的任務(wù)猿棉,然后重新嘗試執(zhí)行任務(wù)(重復(fù)此過程)
ThreadPoolExecutor.CallerRunsPolicy:由調(diào)用線程處理該任務(wù)
用戶也可以實(shí)現(xiàn)接口RejectedExecutionHandler定制自己的策略磅叛。
線程池Demo
這個是在網(wǎng)上找的一個簡單的線程池的實(shí)現(xiàn)代碼:
使用動態(tài)代理方式創(chuàng)建建一個ThreadPoolProxyFactory ,里面提供兩種方式獲取線程池:普通線程池和下載的線程池萨赁。
public class ThreadPoolProxyFactory {
static ThreadPoolProxy mNormalThreadPoolProxy;
static ThreadPoolProxy mDownLoadThreadPoolProxy;
/**
* 得到普通線程池代理對象mNormalThreadPoolProxy
*/
public static ThreadPoolProxy getNormalThreadPoolProxy() {
if (mNormalThreadPoolProxy == null) {
synchronized (ThreadPoolProxyFactory.class) {
if (mNormalThreadPoolProxy == null) {
mNormalThreadPoolProxy = new ThreadPoolProxy(5, 5);
}
}
}
return mNormalThreadPoolProxy;
}
/**
* 得到下載線程池代理對象mDownLoadThreadPoolProxy
*/
public static ThreadPoolProxy getDownLoadThreadPoolProxy() {
if (mDownLoadThreadPoolProxy == null) {
synchronized (ThreadPoolProxyFactory.class) {
if (mDownLoadThreadPoolProxy == null) {
mDownLoadThreadPoolProxy = new ThreadPoolProxy(3, 3);
}
}
}
return mDownLoadThreadPoolProxy;
}
}
線程池代理,替線程池完成一些操作弊琴。提供了三種方法:執(zhí)行任務(wù),提交任務(wù),移除任務(wù)。
public class ThreadPoolProxy {
ThreadPoolExecutor mExecutor;
private int mCorePoolSize;
private int mMaximumPoolSize;
/**
* @param corePoolSize 核心池的大小
* @param maximumPoolSize 最大線程數(shù)
*/
public ThreadPoolProxy(int corePoolSize, int maximumPoolSize) {
mCorePoolSize = corePoolSize;
mMaximumPoolSize = maximumPoolSize;
}
/**
* 初始化ThreadPoolExecutor
* 雙重檢查加鎖,只有在第一次實(shí)例化的時候才啟用同步機(jī)制,提高了性能
*/
private void initThreadPoolExecutor() {
if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) {
synchronized (ThreadPoolProxy.class) {
if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) {
long keepAliveTime = 3000;
TimeUnit unit = TimeUnit.MILLISECONDS;
BlockingQueue workQueue = new LinkedBlockingDeque<>();
ThreadFactory threadFactory = Executors.defaultThreadFactory();
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
mExecutor = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, handler);
}
}
}
}
/**
執(zhí)行任務(wù)和提交任務(wù)的區(qū)別?
1.有無返回值
execute->沒有返回值
submit-->有返回值
2.Future的具體作用?
1.有方法可以接收一個任務(wù)執(zhí)行完成之后的結(jié)果,其實(shí)就是get方法,get方法是一個阻塞方法
2.get方法的簽名拋出了異常===>可以處理任務(wù)執(zhí)行過程中可能遇到的異常
*/
/**
* 執(zhí)行任務(wù)
*/
public void execute(Runnable task) {
initThreadPoolExecutor();
mExecutor.execute(task);
}
/**
* 提交任務(wù)
*/
public Future submit(Runnable task) {
initThreadPoolExecutor();
return mExecutor.submit(task);
}
/**
* 移除任務(wù)
*/
public void remove(Runnable task) {
initThreadPoolExecutor();
mExecutor.remove(task);
}
}
那么我們要怎么使用線程池呢:
ThreadPoolProxyFactory .getNormalThreadPoolProxy().execute(Runnable);
總結(jié)
這個大概就是Android線程池的使用杖爽,有什么不對的地方歡迎大家留言敲董,我們一起交流,寫下大家慰安。
在網(wǎng)上也看到了一個關(guān)于實(shí)現(xiàn)優(yōu)先級線程池的有興趣的朋友也可以學(xué)習(xí)一下實(shí)現(xiàn)優(yōu)先級線程池腋寨。