Java執行緒池(Executor)
- ThreadPoolExecutor使用
/**
* ThreadPoolExecutor 使用測試類
* 在java doc中,並不提倡我們直接使用ThreadPoolExecutor,
* 而是使用Executors類中提供的幾個靜態方法來建立執行緒池
* @author mazaiting
*/
public class ThreadPoolExecutorTest {
/**
* 當前類主方法入口,在主函式中靜態呼叫即可
*/
public static void exec() {
// 例項化執行緒池
// corePoolSize : 核心池的大小(即執行緒池中的執行緒數目大於這個引數時,提交的任務會被放進任務快取佇列)
// maximumPoolSize : 執行緒池最大能容忍的執行緒數
// keepAliveTime : 執行緒存活時間
// unit : 引數keepAliveTime的時間單位
// workQueue : 任務快取佇列,用來存放等待執行的任務
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, 10, 200, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(5));
for (int i = 0; i < 15; i++) {
MyTask task = new MyTask(i);
executor.execute(task); // 執行任務
System.out.println("執行緒池中執行緒數目:"+executor.getPoolSize()+",佇列中等待執行的任務數目:"+
executor.getQueue().size()+",已執行玩別的任務數目:"+executor.getCompletedTaskCount());
}
// 不會立即終止執行緒池,而是要等所有任務快取佇列中的任務都執行完後才終止,但再也不會接受新的任務
executor.shutdown();
}
static class MyTask implements Runnable{
private int taskNum;
public MyTask(int num) {
this.taskNum = num;
}
public void run() {
System.out.println("正在執行task: " + taskNum);
try {
// 當前執行緒睡眠4秒
Thread.currentThread().sleep(4000);
} catch (InterruptedException e) {}
System.out.println("task: " + taskNum + "執行完畢");
}
}
}
執行結果:
正在執行task: 0
執行緒池中執行緒數目:1,佇列中等待執行的任務數目:0,已執行玩別的任務數目:0
執行緒池中執行緒數目:2,佇列中等待執行的任務數目:0,已執行玩別的任務數目:0
正在執行task: 1
正在執行task: 2
執行緒池中執行緒數目:3,佇列中等待執行的任務數目:0,已執行玩別的任務數目:0
執行緒池中執行緒數目:4,佇列中等待執行的任務數目:0,已執行玩別的任務數目:0
正在執行task: 3
執行緒池中執行緒數目:5,佇列中等待執行的任務數目:0,已執行玩別的任務數目:0
執行緒池中執行緒數目:5,佇列中等待執行的任務數目:1,已執行玩別的任務數目:0
執行緒池中執行緒數目:5,佇列中等待執行的任務數目:2,已執行玩別的任務數目:0
執行緒池中執行緒數目:5,佇列中等待執行的任務數目:3,已執行玩別的任務數目:0
執行緒池中執行緒數目:5,佇列中等待執行的任務數目:4,已執行玩別的任務數目:0
執行緒池中執行緒數目:5,佇列中等待執行的任務數目:5,已執行玩別的任務數目:0
正在執行task: 4
執行緒池中執行緒數目:6,佇列中等待執行的任務數目:5,已執行玩別的任務數目:0
正在執行task: 10
執行緒池中執行緒數目:7,佇列中等待執行的任務數目:5,已執行玩別的任務數目:0
正在執行task: 11
執行緒池中執行緒數目:8,佇列中等待執行的任務數目:5,已執行玩別的任務數目:0
正在執行task: 12
執行緒池中執行緒數目:9,佇列中等待執行的任務數目:5,已執行玩別的任務數目:0
正在執行task: 13
執行緒池中執行緒數目:10,佇列中等待執行的任務數目:5,已執行玩別的任務數目:0
正在執行task: 14
task: 1執行完畢
task: 0執行完畢
task: 2執行完畢
正在執行task: 5
正在執行task: 6
task: 4執行完畢
正在執行task: 8
task: 3執行完畢
正在執行task: 9
task: 12執行完畢
task: 13執行完畢
正在執行task: 7
task: 10執行完畢
task: 11執行完畢
task: 14執行完畢
task: 5執行完畢
task: 9執行完畢
task: 6執行完畢
task: 8執行完畢
task: 7執行完畢
- Executors使用
/**
* 執行緒池ExecutorService測試類
* @author mazaiting
*/
public class ExecutorsTest {
public static void exec() {
/**
* CachedThreadPool會建立一個快取區,將初始化的執行緒快取起來。會終止並且從快取中移除已有60秒未被使用的執行緒。
* 如果執行緒有可用的,就使用之前建立好的執行緒,
* 如果執行緒沒有可用的,就新建立執行緒。
*
* 重用:快取型池子,先檢視池中有沒有以前建立的執行緒,如果有,就reuse;如果沒有,就建一個新的執行緒加入池中
* 使用場景:快取型池子通常用於執行一些生存期很短的非同步型任務,因此在一些面向連線的daemon型SERVER中用得不多。
* 超時:能reuse的執行緒,必須是timeout IDLE內的池中執行緒,預設timeout是60s,超過這個IDLE時長,執行緒例項將被終止及移出池。
* 結束:注意,放入CachedThreadPool的執行緒不必擔心其結束,超過TIMEOUT不活動,其會自動被終止。
*/
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
/**
* 在FixedThreadPool中,有一個固定大小的池。
* 如果當前需要執行的任務超過池大小,那麼多出的任務處於等待狀態,直到有空閒下來的執行緒執行任務,
* 如果當前需要執行的任務小於池大小,空閒的執行緒也不會去銷燬。
*
* 重用:fixedThreadPool與cacheThreadPool差不多,也是能reuse就用,但不能隨時建新的執行緒
* 固定數目:其獨特之處在於,任意時間點,最多隻能有固定數目的活動執行緒存在,此時如果有新的執行緒要建立,只能放在另外的佇列中等待,直到當前的執行緒中某個執行緒終止直接被移出池子
* 超時:和cacheThreadPool不同,FixedThreadPool沒有IDLE機制(可能也有,但既然文件沒提,肯定非常長,類似依賴上層的TCP或UDP IDLE機制之類的),
* 使用場景:所以FixedThreadPool多數針對一些很穩定很固定的正規併發執行緒,多用於伺服器
* 原始碼分析:從方法的原始碼看,cache池和fixed 池呼叫的是同一個底層池,只不過引數不同:
* fixed池執行緒數固定,並且是0秒IDLE(無IDLE)
* cache池執行緒數支援0-Integer.MAX_VALUE(顯然完全沒考慮主機的資源承受能力),60秒IDLE
*/
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
/**
* ScheduledThreadPool是一個固定大小的執行緒池,與FixedThreadPool類似,執行的任務是定時執行。
*/
ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
/**
* SingleThreadExecutor得到的是一個單個的執行緒,這個執行緒會保證你的任務執行完成。
* 如果當前執行緒意外終止,會建立一個新執行緒繼續執行任務,這和我們直接建立執行緒不同,也和newFixedThreadPool(1)不同。
*/
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
/**
* 建立一個單執行緒執行器,它可以排程命令在給定的延遲之後執行,或者定期執行。(注意,如果此單執行緒由於在關閉前執行失敗而終止,
* 則新執行緒將在需要執行後續任務時取代其位置。)任務可以保證按順序執行,在任何給定的時間內,不超過一個任務是活動的。
* 與其他等效的{ @ code newScheduledThreadPool(1)}不同的是,返回的executor不能被重新配置以使用額外的執行緒。
*/
ExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
/**
* 建立一個系統所能容納的執行緒池大小(Runtime.getRuntime().availableProcessors())
* 作為並行級別
*/
ExecutorService workStealingPool = Executors.newWorkStealingPool();
run(cachedThreadPool);
// run(fixedThreadPool);
// run(scheduledThreadPool);
// run(singleThreadExecutor);
// run(singleThreadScheduledExecutor);
// run(workStealingPool);
}
/**
* 執行任務
* @param cachedThreadPool 執行緒池服務
*/
private static void run(ExecutorService threadPool) {
for (int i = 0; i < 5; i++) {
final int taskID = i;
threadPool.execute(new Runnable() {
public void run() {
for (int j = 0; j < 5; j++) {
try {
// 為了測試出效果,讓每次任務執行都需要一定時間
Thread.currentThread().sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("第" + taskID + "次任務的第" + j + "次執行");
}
}
});
}
// 不會立即終止執行緒池,而是要等所有任務快取佇列中的任務都執行完後才終止,但再也不會接受新的任務
threadPool.shutdown();
}
}
run(cachedThreadPool)執行結果如下:
第4次任務的第0次執行
第1次任務的第0次執行
第0次任務的第0次執行
第3次任務的第0次執行
第2次任務的第0次執行
第0次任務的第1次執行
第4次任務的第1次執行
第2次任務的第1次執行
第3次任務的第1次執行
第1次任務的第1次執行
第1次任務的第2次執行
第0次任務的第2次執行
第2次任務的第2次執行
第4次任務的第2次執行
第3次任務的第2次執行
第1次任務的第3次執行
第4次任務的第3次執行
第0次任務的第3次執行
第3次任務的第3次執行
第2次任務的第3次執行
第1次任務的第4次執行
第4次任務的第4次執行
第2次任務的第4次執行
第0次任務的第4次執行
第3次任務的第4次執行
run(fixedThreadPool)執行結果如下:
第2次任務的第0次執行
第1次任務的第0次執行
第0次任務的第0次執行
第2次任務的第1次執行
第1次任務的第1次執行
第0次任務的第1次執行
第1次任務的第2次執行
第0次任務的第2次執行
第2次任務的第2次執行
第1次任務的第3次執行
第0次任務的第3次執行
第2次任務的第3次執行
第1次任務的第4次執行
第0次任務的第4次執行
第2次任務的第4次執行
第3次任務的第0次執行
第4次任務的第0次執行
第3次任務的第1次執行
第4次任務的第1次執行
第3次任務的第2次執行
第4次任務的第2次執行
第4次任務的第3次執行
第3次任務的第3次執行
第3次任務的第4次執行
第4次任務的第4次執行
run(scheduledThreadPool)執行結果如下:
第2次任務的第0次執行
第1次任務的第0次執行
第0次任務的第0次執行
第0次任務的第1次執行
第2次任務的第1次執行
第1次任務的第1次執行
第1次任務的第2次執行
第2次任務的第2次執行
第0次任務的第2次執行
第2次任務的第3次執行
第0次任務的第3次執行
第1次任務的第3次執行
第2次任務的第4次執行
第1次任務的第4次執行
第0次任務的第4次執行
第3次任務的第0次執行
第4次任務的第0次執行
第3次任務的第1次執行
第4次任務的第1次執行
第3次任務的第2次執行
第4次任務的第2次執行
第3次任務的第3次執行
第4次任務的第3次執行
第3次任務的第4次執行
第4次任務的第4次執行
run(singleThreadExecutor)執行結果如下:
第0次任務的第0次執行
第0次任務的第1次執行
第0次任務的第2次執行
第0次任務的第3次執行
第0次任務的第4次執行
第1次任務的第0次執行
第1次任務的第1次執行
第1次任務的第2次執行
第1次任務的第3次執行
第1次任務的第4次執行
第2次任務的第0次執行
第2次任務的第1次執行
第2次任務的第2次執行
第2次任務的第3次執行
第2次任務的第4次執行
第3次任務的第0次執行
第3次任務的第1次執行
第3次任務的第2次執行
第3次任務的第3次執行
第3次任務的第4次執行
第4次任務的第0次執行
第4次任務的第1次執行
第4次任務的第2次執行
第4次任務的第3次執行
第4次任務的第4次執行
run(singleThreadScheduledExecutor)執行結果如下:
第0次任務的第0次執行
第0次任務的第1次執行
第0次任務的第2次執行
第0次任務的第3次執行
第0次任務的第4次執行
第1次任務的第0次執行
第1次任務的第1次執行
第1次任務的第2次執行
第1次任務的第3次執行
第1次任務的第4次執行
第2次任務的第0次執行
第2次任務的第1次執行
第2次任務的第2次執行
第2次任務的第3次執行
第2次任務的第4次執行
第3次任務的第0次執行
第3次任務的第1次執行
第3次任務的第2次執行
第3次任務的第3次執行
第3次任務的第4次執行
第4次任務的第0次執行
第4次任務的第1次執行
第4次任務的第2次執行
第4次任務的第3次執行
第4次任務的第4次執行
run(workStealingPool)未執行出結果,從Java 1.8開始存在
相關文章
- 執行緒池 Executor執行緒
- 執行緒池和Executor框架執行緒框架
- Java多執行緒學習(八)執行緒池與Executor 框架Java執行緒框架
- 奈學:Executor執行緒池的概述執行緒
- Java多執行緒之Executor框架和手寫簡易的執行緒池Java執行緒框架
- 併發07--執行緒池及Executor框架執行緒框架
- Java執行緒池二:執行緒池原理Java執行緒
- Java多執行緒——執行緒池Java執行緒
- Java執行緒池Java執行緒
- java 執行緒池Java執行緒
- java執行緒池趣味事:這不是執行緒池Java執行緒
- java多執行緒9:執行緒池Java執行緒
- Java多執行緒18:執行緒池Java執行緒
- Java 執行緒 Executor 框架詳解與使用Java執行緒框架
- 搞懂Java執行緒池Java執行緒
- Java Executors(執行緒池)Java執行緒
- 多執行緒知識梳理(5) 執行緒池四部曲之 Executor 框架執行緒框架
- Java多執行緒-執行緒池的使用Java執行緒
- Java執行緒池一:執行緒基礎Java執行緒
- 【Java】【多執行緒】執行緒池簡述Java執行緒
- java多執行緒系列之執行緒池Java執行緒
- Java併發程式設計之Executor執行緒池原理與原始碼解讀Java程式設計執行緒原始碼
- Java 執行緒池執行原理分析Java執行緒
- java--執行緒池--建立執行緒池的幾種方式與執行緒池操作詳解Java執行緒
- Android執行緒篇(二)Java執行緒池Android執行緒Java
- 速讀Java執行緒池Java執行緒
- java執行緒池實踐Java執行緒
- Java 執行緒池詳解Java執行緒
- java-執行緒池(一)Java執行緒
- Java執行緒池歸納Java執行緒
- JAVA執行緒池的使用Java執行緒
- Java執行緒池進階Java執行緒
- Java review--執行緒池JavaView執行緒
- Java(Android)執行緒池JavaAndroid執行緒
- Java 執行緒池學習Java執行緒
- Java執行緒池詳解Java執行緒
- 效能三倍於JDK標準執行緒池Executor服務JDK執行緒
- Java利用執行緒工廠監控執行緒池Java執行緒