線程池的介紹
顧名思義線程池就是線程的池子,而這個池子它可以管理一個或多個線程,包括線程的創(chuàng)建以及使用炉爆,而身為Android開發(fā)至少對線程的使用還是多少了解的吧,畢竟Android建議我們將耗時操作放入到后臺線程去進行以及4.0以后強制我們只有在后臺線程中才能進行網(wǎng)絡(luò)訪問猪落,這樣就不會因為某些操作阻塞了UI線程中從而導(dǎo)致ANR(Android無響應(yīng))了。
線程池的使用
常見的線程池包括:
單線程的線程池
固定線程數(shù)的線程池
動態(tài)線程數(shù)的的線程池
自定義的線程池
接下來我就會從下面這些線程池入手分別介紹他們的使用和工作機制:
1.單線程的線程池
創(chuàng)建和使用單線程的線程池:
兩個方法可以獲取:ExecutorService newSingleThreadExecutor()
ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory )
// 創(chuàng)建單線程的線程池并執(zhí)行
ExecutorService threadPool = Executors.newSingleThreadExecutor();
threadPool.execute(new SlowTask("task0"));
threadPool.execute(new SlowTask("task1"));
threadPool.execute(new SlowTask("task2"));
// 要做的任務(wù)
private static class SlowTask implements Runnable {
private String name;
public SlowTask(String name) {
this.name = name;
}
@Override
public void run() {
Log.i(TAG, "SlowTask " + name + " is running");
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 10000; j++) {
// 假裝很耗時
}
}
}
@Override
public String toString() {
return "SlowTask:" + name;
}
}
單線程的線程池的工作機制:
2.固定線程數(shù)的線程池:
兩個方法可以獲取:ExecutorService newFixedThreadPool(int threadCount)
ExecutorService newFixedThreadPool(int threadCount, ThreadFactory threadFactory )
// 創(chuàng)建一個固定5個線程數(shù)的線程池
ExecutorService threadPool = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
threadPool.execute(new SlowTask ("task" + i));
}
固定的線程池的工作機制:
3.動態(tài)線程數(shù)的線程池:
兩個方法可以獲取:ExecutorService newCachedThreadPool()
ExecutorService newCachedThreadPool(ThreadFactory threadFactory )
// 創(chuàng)建動態(tài)線程數(shù)的線程池通過自定義一個ThreadFactory
ExecutorService threadPool = Executors.newCachedThreadPool(5);
for (int i = 0; i < 10; i++) {
threadPool.execute(new SlowTask ("task" + i));
}
// 自定義的線程工廠
private static class MyThreadFactory implements ThreadFactory {
private static int count = 0;
@Override
public Thread newThread(Runnable r) {
Log.i(TAG, "第 " + (count++) + " 個線程創(chuàng)建");
return new Thread(r);
}
}
動態(tài)線程數(shù)的線程池的工作機制:
4.自定義的的線程池:
想要使用自定義線程池的時候我們需要使用到一個類——ThreadPoolExecutor畴博,其實我們在創(chuàng)建上面那三個線程池的時候都是Executors幫我們?nèi)ネㄟ^創(chuàng)建ThreadPoolExecutor來實現(xiàn)的笨忌,如圖:
這個時候我們來看看ThreadPoolExecutor類的構(gòu)造函數(shù),當我們看構(gòu)造函數(shù)我們就知道傳哪些參數(shù)就可以幫我實現(xiàn)相同的效果或者他上面三個完全不同的效果,我們來看一個最長的構(gòu)造函數(shù):
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory ,
RejectedExecutionHandler handler)
那我就從上到下一個個來說明他們的含義:
1.corePoolSize:核心線程數(shù)
2.maximumPoolSize:核心線程數(shù)
3.keepAliveTime:空閑線程的存活時間
4.unit:空閑線程存活時間的單位
5.workQueue:任務(wù)等待隊列
6.threadFactory:線程工廠
7.handler:處理器, 當線程數(shù)已經(jīng)滿了, 也已經(jīng)沒有空閑線程了, 并且且任務(wù)等待隊列隊列也滿了, 接受不了任務(wù)了的時候就會把該任務(wù)交給handler進行處理俱病。
在了解了構(gòu)造器這些參數(shù)之后就可以很方便我們自定義線程池了(當然還有多個構(gòu)造函數(shù), 所以不一定使用這一個, 這是參數(shù)最多的構(gòu)造函數(shù)):
// 創(chuàng)建了一個核心線程數(shù)為2官疲,最大線程數(shù)為10的自定義線程
ExecutorService threadPool = new ThreadPoolExecutor(2, 10,
60L, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(10),
new MyThreadFactory(),
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
Log.i(TAG, "被拒任務(wù)名稱是: " + r.toString());
}
});
for (int i = 0; i < 20; i++) {
try {
threadPool.execute(new SlowTask("Task" + i));
} catch (Exception e) {
Log.e(TAG, e.toString());
}
}
自定義線程池的工作機制:
5.關(guān)閉線程池
調(diào)用shutdown()或者調(diào)用shutdownNow()就可以了,可以通過isShutdown()判斷是否關(guān)閉.
shutdown()和shutdownNow()的區(qū)別如下圖:
6.各個線程池的使用場景
線程池的實踐
我使用上述各類線程池寫了一個圖片預(yù)覽器, App截圖如下(手機截圖有點大):
下面獲取到的妹子圖片來自Gank.io, 如果是單線程的線程池圖片會一張一張顯示出來, 而固定線程我寫了3個亮隙,所以會三個三個顯示出來途凫,而動態(tài)線程數(shù)的線程池和自定義線程池都是會一口氣顯示很多
項目我已上傳Github, 地址為https://github.com/GzwJaaaelu/ThreadPoolExecutorDemo
Demo可能還有待完善的地方,請大家指出溢吻。
我希望可以站在初學(xué)者&自學(xué)者的角度把Android中的知識點很清楚的介紹給大家维费,希望大家喜歡。 如果有錯誤希望指出來煤裙,有問題或者沒看懂掩完,都可以來問我的