簡介
在探討時 ThreadPoolExecutor 只介紹了FixedThreadPool抑堡、CachedThreadPool巡雨、SingleThreadExecutor骇径,并沒有去介紹ScheduledThreadPoolExecutor炊林,因為 ScheduledThreadPoolExecutor 與其他線程池的概念有些區(qū)別堵未,它是一個支持任務周期性調(diào)度的線程池。
ScheduledThreadPoolExecutor 繼承 ThreadPoolExecutor赂苗,同時通過實現(xiàn) ScheduledExecutorSerivce 來擴展基礎(chǔ)線程池的功能愉耙,使其擁有了調(diào)度能力。其整個調(diào)度的核心在于內(nèi)部類 DelayedWorkQueue 拌滋,一個有序的延時隊列朴沿。
ScheduledThreadPoolExecutor 的出現(xiàn),很好的彌補了傳統(tǒng) Timer 的不足,具體對比看下表:
Timer | ScheduledThreadPoolExecutor | |
---|---|---|
線程 | 單線程 | 多線程 |
多任務 | 任務之間相互影響 | 任務之間不影響 |
調(diào)度時間 | 絕對時間 | 相對時間 |
異常 | 單任務異常赌渣, 后續(xù)任務受影響 |
無影響 |
構(gòu)造方法
ScheduledThreadPoolExecutor有三個構(gòu)造形式:
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory);
}
public ScheduledThreadPoolExecutor(int corePoolSize,
RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), handler);
}
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory, handler);
}
關(guān)于父類的構(gòu)造可參見 ThreadPoolExecutor魏铅。當然我們也可以使用工具類Executors的newScheduledThreadPool的方法,快速創(chuàng)建坚芜。注意這里使用的DelayedWorkQueue沦零。
ScheduledThreadPoolExecutor沒有提供帶有最大線程數(shù)的構(gòu)造函數(shù)的,默認是Integer.MAX_VALUE货岭,說明其可以無限制的開啟任意線程執(zhí)行任務路操,在大量任務系統(tǒng),應注意這一點千贯,避免內(nèi)存溢出屯仗。
核心方法
核心方法主要介紹ScheduledThreadPoolExecutor的調(diào)度方法,其他方法與 ThreadPoolExecutor 一致搔谴。調(diào)度方法均由 ScheduledExecutorService 接口定義:
public interface ScheduledExecutorService extends ExecutorService {
// 特定時間延時后執(zhí)行一次Runnable
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
// 特定時間延時后執(zhí)行一次Callable
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
// 固定周期執(zhí)行任務(與任務執(zhí)行時間無關(guān)魁袜,周期是固定的)
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
// 固定延時執(zhí)行任務(與任務執(zhí)行時間有關(guān),延時從上一次任務完成后開始)
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
}
代碼中注釋了每個方法的作用敦第,需注意固定周期與固定延時的區(qū)別峰弹。下面分別對這些方法進行測試:
public class ScheduledPoolTest {
private static final SimpleDateFormat FORMAT = new SimpleDateFormat("hh:mm:ss");
private static final Random RANDOM = new Random();
/**
* 輸出:
* 11:04:32
11:04:35
*/
public static void schedule() {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
printTime();
scheduledExecutorService.schedule(new Task(), 3, TimeUnit.SECONDS);
}
/**
* 輸出:
* 11:05:34
11:05:36
11:05:46
11:05:56
11:06:06
11:06:16
......
*/
public static void scheduleAtFixedRate() {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
printTime();
scheduledExecutorService.scheduleAtFixedRate(new Task(), 2, 10, TimeUnit.SECONDS);
}
/**
* 輸出:
* 11:07:39
11:07:41
11:07:54
11:08:08
11:08:22
11:08:33
......
*/
public static void scheduleWithFixedDelay() {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
printTime();
scheduledExecutorService.scheduleWithFixedDelay(new Task(), 2, 10, TimeUnit.SECONDS);
}
static class Task implements Runnable{
public void run() {
printTime();
try {
Thread.sleep(RANDOM.nextInt(5) * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void printTime() {
Date date = new Date();
System.out.println(FORMAT.format(date));
}
}
為了體現(xiàn)scheduleAtFixedRate和scheduleWithFixedDelay的差別,在代碼中我們加入了隨機睡眠時間芜果,使任務執(zhí)行不確定鞠呈。從注釋中的輸出我們可以看到scheduleAtFixedRate的任務運行周期不受任務執(zhí)行時間的影響,而scheduleWithFixedDelay的任務運行周期受任務執(zhí)行時間影響較大右钾。
但需注意蚁吝,如果任務的執(zhí)行時間超過任務調(diào)度周期,比如任務執(zhí)行需要10s舀射,而給定執(zhí)行時間間隔是5s的話窘茁,任務的調(diào)度是在任務10s執(zhí)行完之后立即重新執(zhí)行,而不是5s的周期脆烟。
總結(jié)
ScheduledThreadPoolExecutor 在 ThreadPoolExecutor 的基礎(chǔ)上擴展了 線程周期調(diào)度功能山林,使用時應注意控制其調(diào)度的時間點。
多線程系列目錄(不斷更新中):
線程啟動原理
線程中斷機制
多線程實現(xiàn)方式
FutureTask實現(xiàn)原理
線程池之ThreadPoolExecutor概述
線程池之ThreadPoolExecutor使用
線程池之ThreadPoolExecutor狀態(tài)控制
線程池之ThreadPoolExecutor執(zhí)行原理
線程池之ScheduledThreadPoolExecutor概述
線程池之ScheduledThreadPoolExecutor調(diào)度原理
線程池的優(yōu)雅關(guān)閉實踐