前言
上節講了講自定義線程池,今天我們來聊聊線程池框架,在實際開發中我們還是基本使用線程框架Executor給我們提供的一些工具類,Java提供的Executor都在JUC(java.util.concurrent)包下面,主要包括:線程池工廠類Executors,線程池實現類ThreadPoolExecutor等,今天呢我們主要聊聊Executors,看看通過Executors我們可以做什麼?OK,不多說廢話,我們馬上進入今天的主題,讓我們揚帆起航,開啓今天的併發之旅吧。
什麼是Executors?
Executors,扮演的是線程工廠的角色,一定要與Executor相區分開,Executors只是Executor框架中的一個工廠類而已,通過Executors我們可以創建特定功能的線程池(ThreadPoolExecutor),通過這句話你是不是對Executors和ThreadPoolExecutor的關係有了一定的認識,這兩個都是Executor框架中的一部分(關於Executor框架的各個成員組成這裏就先不做說明,今天主要是學會怎麼使用線程工廠創建線程池)。
如何使用Executors?
線程池ThreadPoolExecutor通常都是通過Executors來創建的,我們可以根據自己的需求創建下面幾種不同作用的線程池:
// 創建一個固定數量的線程池
ExecutorService ExecutorService1 = Executors.newFixedThreadPool(10);
// 返回一個可根據實際情況調整線程個數的線程池
ExecutorService ExecutorService2 = Executors.newCachedThreadPool();
// 創建一個線程數量爲1的線程池
ExecutorService ExecutorService3 = Executors.newSingleThreadExecutor();
// 返回一個ScheduledExecutorService對象,該對象也是調用父類的線程池方法,類似newFixedThreadPool
ScheduledExecutorService ScheduledExecutorService = Executors.newScheduledThreadPool(5);
線程池的使用之前講自定義線程池已經說過了,主要也就是:
-
execute向線程池提交任務
-
shutdown和shutdownNow關閉線程池
newFixedThreadPool:該方法返回一個固定數量的線程池,該方法的線程數量始終不變,當有任務提交時,若線程池中有空閒線程,則立即執行,若沒有,則會被緩存在一個任務隊列中等待有空閒的線程再去執行;(核心線程數等於最大線程數,默認空閒時間爲0,空閒立馬銷燬),該方法有2個實現,我們看下面源碼:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}
再分別看下這2個方法在線程池中的實現:
// 我們會發現沒有傳入線程工廠的方法調用了一個默認的線程工廠
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
// 而有傳入線程工廠的方法調用自己傳入的線程工廠
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
newSingleThreadExecutor:創建一個線程數量爲1的線程池,若空閒則執行,否則入隊列等待被執行;(核心線程數量爲1,最大線程數量也爲1,空閒等待時間爲0),該方法也有2個實現,一個帶自定義的線程工廠,一個不帶:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory));
}
newCachedThreadPool:返回一個可根據實際情況調整線程個數的線程池,不限制最大線程數量,若有任務則沒線程時則創建線程,每個線程空閒等待時間爲60秒,60秒後如果該線程沒有任務可執行,則被回收;(核心線程數量爲0,最大線程數量爲最大,空閒等待時間爲60s)
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}
本文由“壹伴編輯器”提供技術支持
newScheduledThreadPool:返回一個ScheduledExecutorService對象,該線程池可以指定線程數量
// 返回一個ScheduledExecutorService對象
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
// 調了父類super的方法裏面還是一個ThreadPoolExecutor
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
new DelayedWorkQueue());
}
// 父類super中的ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}