Executor 框架
Executor 框架簡介
爲了更好的控制多線程,JDK 提供了一套線程框架 Executor,幫助開發人員有限的進行線程控制,它們都在 java.util.concurrent包中,是 JDK 併發包的核心,其中有一個比較重要的類:Executors, 它扮演着線程工廠的角色,我們通過 Executors可以創建特定功能的線程池。
Executors 創建線程池方法
newFixedThreadPool()
newFixedThreadPool,該方法返回一個固定數量的線程池,該方法的線程數始終不變,當有一個任務提交時,若線程池中空閒,則立即執行,若沒有,則會被緩存在一個任務隊列中等待有空閒的線程去執行
newSingleThreadExecutor()
newSingleThreadExecutor,該方法會創建一個線程的線程池,若空閒則執行,若沒有空閒線程,則緩存在任務隊列中。
newCachedThreadPool()
newCachedThreadPool,返回一個可以根據實際情況調整線程個數的線程池,不限制最大的線程數量,若有空閒的線程,則執行任務,若無任務則不創建線程,並且每一個空閒線程會在60秒後自動回收
newScheduledThreadPool()
newScheduledThreadPool,返回一個SchededExecutorService對象,但該線程池可以指定線程的數量
更多
通過 ThreadPoolExecutor類去 自定義線程池
Executors工廠類無法滿足我們的需求,我們可以自己去創建自定義的線程池,其實 Executors工廠類裏面的創建線程方法內部都是採用 ThreadPoolExecutor類,這個類可以自定義線程,其構造方法如下
public ThreadPoolExecutor(
int corePoolSize,//核心線程數
int maximumPoolSize,//線程池的最大線程數
long keepAliveTime,//線程池裏面的線程的存活時間
TimeUnit unit,// 時間單位
BlockingQueue<Runnable> workQueue,// 當線程池中沒有空閒線程的時候, 存放任務的阻塞隊列
ThreadFactory threadFactory,// 線程工廠
RejectedExecutlonHandler handler//當阻塞隊列也滿了的情況下,可以使用 這個處理者
) {
...
}
jdk 幫我們實現的 線程池
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
通過 ThreadPoolExecutor類去 自定義線程池 實戰
package cn.istarfinancial.demo;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @Author: huangwenjun
* @Description:
* @Date: Created in 14:43 2018/5/15
**/
public class ThreadTest {
public static void main(String[] args) throws Exception {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
1, 2, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(1));
Runnable task1 = new Runnable() {
@Override
public void run() {
try {
System.out.println("do task 1 and start sleep....");
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable task2 = new Runnable() {
@Override
public void run() {
try {
System.out.println("do task 2 and start sleep....");
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable task3 = new Runnable() {
@Override
public void run() {
try {
System.out.println("do task 3 and start sleep....");
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable task4 = new Runnable() {
@Override
public void run() {
try {
System.out.println("do task 4 and start sleep....");
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
threadPoolExecutor.submit(task1);
System.out.println("after submit task1, poolSize :" + threadPoolExecutor.getPoolSize() + ", queueSize:" + threadPoolExecutor.getQueue().size());
threadPoolExecutor.submit(task2);
System.out.println("after submit task2, poolSize :" + threadPoolExecutor.getPoolSize() + ", queueSize:" + threadPoolExecutor.getQueue().size());
threadPoolExecutor.submit(task3);
System.out.println("after submit task3, poolSize :" + threadPoolExecutor.getPoolSize() + ", queueSize:" + threadPoolExecutor.getQueue().size());
// threadPoolExecutor.submit(task4);
// System.out.println("after submit task4, poolSize :" + threadPoolExecutor.getPoolSize() + ", queueSize:" + threadPoolExecutor.getQueue().size());
}
}
- 輸出
after submit task1, poolSize :1, queueSize:0
after submit task2, poolSize :1, queueSize:1
after submit task3, poolSize :2, queueSize:1
do task 1 and start sleep....
do task 3 and start sleep....
結論
// 結論 隨着任務不斷增多 順序如下
// 1 加入的任務 首先交給 核心線程執行,當核心線程耗盡
// 2 將任務 交給指定的阻塞隊列, 當阻塞隊列 耗盡
// 3 將根據指定最大線程數創建線程去執行任務, 當所有線程耗盡
// 4 調用拒絕策略 如果未指定策略,則會拋出異常