目錄ScheduledThreadPoolExecutor一、概述二、常用方法1、schedule 方法2、scheduleAtFixedRate方法3.scheduleWithFixedDelay方法三、ScheduledExecutorService的創建方式 ScheduledThreadPo ...
目錄
ScheduledThreadPoolExecutor
一、概述
java 中ScheduledExecutorService介面是基於線程池設計的定時任務類,每個調度任務都會分配到線程池中的一個線程去執行,也就是說,任務是併發執行,互不影響。
其中的一個實現類是ScheduledThreadPoolExecutor
(1)>ScheduledThreadPoolExecutor實現ScheduledExecutorService介面,實現了一些定時任務處理的方法。
(2)>ScheduledThreadPoolExecutor繼承了ThreadPoolExecutor,可以通過線程池進行任務的管理和調度。
二、常用方法
1、schedule 方法
該方法的作用是提交一個延遲執行的任務,任務從提交時間算起延遲單位unit的deplay時間後執行,提交的不是周期任務,任務只會執行一次
ScheduledFuture<?> schedule(Runnable var1, long period, TimeUnit var4);
ScheduledFuture<V> schedule(Callable<V> var1, long var2, TimeUnit var4);
參數解析:
- Runnable 需要運行的任務
- period 間隔時間
- unit參數是時間單元
代碼demo:
ScheduledExecutorService service = new ScheduledThreadPoolExecutor(1);
System.out.println("當前時間為:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
// 使用的Runnable 匿名函數編寫的
service.schedule(() -> {
System.out.println("我是使用schedule方法執行");
Thread thread = Thread.currentThread();
System.out.println("我是間隔1s執行的任務,線程名稱為:" + thread.getName() + ",線程ID為:" + thread.getId() + ",當前時間:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}, 1, TimeUnit.SECONDS); // 延1秒後開始執行
ScheduledExecutorService service = new ScheduledThreadPoolExecutor(1);
System.out.println("當前時間為:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
service.schedule(new Runnable() {
@Override
public void run() {
System.out.println("我是使用schedule方法執行");
Thread thread = Thread.currentThread();
System.out.println("我是間隔1s執行的任務,線程名稱為:" + thread.getName() + ",線程ID為:" + thread.getId() + ",當前時間:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
}, 1, TimeUnit.SECONDS); // 延1秒後開始執行
ScheduledExecutorService service = new ScheduledThreadPoolExecutor(1);
//使用 Callable 實現,該實現有返回值,可以接收返回的數據
ScheduledFuture<Object> future = service.schedule(new Callable<Object>() {
@Override
public Object call() throws Exception {
System.out.println("我是使用schedule方法執行");
Thread thread = Thread.currentThread();
System.out.println("我是間隔1s執行的任務,線程名稱為:" + thread.getName() + ",線程ID為:" + thread.getId() + ",當前時間:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
return null;
}
}, 1, TimeUnit.SECONDS);// 延1秒後開始執行
Object o = future.get();
System.out.println(o);
輸出結果為:
當前時間為:2024-03-18 14:31:01
我是使用schedule方法執行
我是間隔1s執行的任務,線程名稱為:pool-1-thread-1,線程ID為:21,當前時間:2024-03-18 14:31:02
2、scheduleAtFixedRate方法
該方法相對起始時間點以固定頻率調用指定的任務(fixed-rate任務)。當把任務提交到線程池並延遲initialDelay時間後開始執行任務command。然後從initialDelay+period時間點再次執行,而後在initialDelay+2*period時間點再次執行,迴圈往複,直到拋出異常或者調用了任務的cancel方法取消了任務,或者關閉了線程池。
參數講解:
- command 任務實例
- initialDelay參數是初始化延遲時間
- period參數是間隔時間
- unit參數是時間單元
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
(1):當任務實例commod執行的時間小於延遲間隔時間delay情況
ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1);
System.out.println("當前時間為:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("開始測試,當前時間為:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("結束測試,當前時間為:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
}, 5, 5, TimeUnit.SECONDS); // 延遲5秒後執行,每隔3秒執行一次
執行結果為:
當前時間為:2024-03-18 15:15:06
開始測試,當前時間為:2024-03-18 15:15:11
結束測試,當前時間為:2024-03-18 15:15:14
#第二次執行時間是第一次時間 + period 即11 + 5 = 16;
開始測試,當前時間為:2024-03-18 15:15:16
結束測試,當前時間為:2024-03-18 15:15:19
(2):當任務實例commod執行的時間大於間隔時間period情況
修改 TimeUnit.SECONDS.sleep(3); 為 TimeUnit.SECONDS.sleep(6);,執行查看運行結果!
執行結果為:
當前時間為:2024-03-18 15:19:57
開始測試,當前時間為:2024-03-18 15:20:02
結束測試,當前時間為:2024-03-18 15:20:08
開始測試,當前時間為:2024-03-18 15:20:09
結束測試,當前時間為:2024-03-18 15:20:15
總結
ScheduleAtFixedRate 每次執行時間為上一次任務開始起向後推一個時間間隔。分為兩種情況:
(1)若command執行的時間小於period若每次執行時間為 :initialDelay, initialDelay+period, initialDelay+2period, …;
(2)若command執行的時間大於period,則command執行完,下一次任務將立即執行!下即下一次任務不會按照預期的時間間隔執行,每次執行時間為 :initialDelay, initialDelay+taskExecutorTIme, initialDelay+2*taskExecutorTIme, …;
taskExecutorTIme為任務執行的時間!
3.scheduleWithFixedDelay方法
該方法的作用是,當任務執行完畢後,讓其延遲固定時間後再次運行(fixed-delay任務)。其中initialDelay表示提交任務後延遲多少時間開始執行任務command,delay表示當任務執行完畢後延長多少時間後再次運行command任務,unit是initialDelay和delay的時間單位。任務會一直重覆運行直到任務中拋出了異常,被取消了,或者關閉了線程池。
參數:
- command參數是任務實例,
- initialDelay參數是初始換延遲時間,
- delay參數是延遲間隔時間,
- unit參數是時間單元
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
(1):當任務實例commod執行的時間小於延遲間隔時間delay情況
ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1);
System.out.println("當前時間為:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.out.println("開始測試,當前時間為:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("結束測試,當前時間為:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
}, 5, 3, TimeUnit.SECONDS); // 延遲5秒後執行,每隔3秒執行一次
執行結果:
當前時間為:2024-03-18 15:34:23
開始測試,當前時間為:2024-03-18 15:34:28
結束測試,當前時間為:2024-03-18 15:34:29
#第二次執行的時間 == 第一次任務開始時間+任務處理時間+delay延遲時間
#即 32 == 28 + 3秒 + 3秒
開始測試,當前時間為:2024-03-18 15:34:32
結束測試,當前時間為:2024-03-18 15:34:33
(2):當任務實例commod執行的時間大於延遲間隔時間delay情況
修改 TimeUnit.SECONDS.sleep(3); 為 TimeUnit.SECONDS.sleep(6);,執行查看運行結果!
當前時間為:2024-03-18 15:38:28
開始測試,當前時間為:2024-03-18 15:38:33
結束測試,當前時間為:2024-03-18 15:38:39
#第二次任務執行開始時間 == 第一次任務執行開始時間 + 任務處理的時間 + delay延遲時間
#即 42 == 33 + 6 + 3
開始測試,當前時間為:2024-03-18 15:38:42
結束測試,當前時間為:2024-03-18 15:38:48
3:總結
不管任務command執行的時間是多長,下一次任務的執行時間都是上一次任務執行完後在等待延遲間隔delay時間後執行下一次任務。
ScheduleWithFixedDelay 每次執行時間為上一次任務結束起向後推一個時間間隔,即每次執行時間為:initialDelay, initialDelay+executeTime+delay, initialDelay+2executeTime+2delay
三、ScheduledExecutorService的創建方式
public static void classCreate() {
// 方式一
ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1);
// 方式二,方式二和方式一可以等價
ScheduledExecutorService scheduledExecutorService1 = Executors.newScheduledThreadPool(1);
}
參考地址:
https://www.cnblogs.com/xuwc/p/14053613.html