定時任務和延時任務的了解
- ScheduledExecutorService#scheduleAtFixedRate() 指的是“以固定的頻率”執行,period(周期)指的是兩次成功執行之間的時間。上一個任務開始的時間計時,一個period後,檢測上一個任務是否執行完畢,如果上一個任務執行完畢,則目前任務立即執行,如果上一個任務沒有執行完畢,則需要等上一個任務執行完畢後立即執行。
- ScheduledExecutorService#scheduleWithFixedDelay() 指的是“以固定的延時”執行,delay(延時)指的是一次執行終止和下一次執行開始之間的延遲。
示例
scheduleAtFixedRate
public static void main(String[] args) {
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat(
"my-test-pool-%d").build();
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1, threadFactory);
Date startTime = new Date();
System.out.println("startTime: " + startTime.toString());
scheduledExecutorService.scheduleAtFixedRate(() -> {
System.out.println("beginTime: " + new Date().toString());
try {
Thread.sleep(5 * 1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("endTime: " + new Date().toString());
}, 2, 3, TimeUnit.SECONDS);
}
輸出:
startTime: Sun Feb 16 11:17:09 CST 2020
beginTime: Sun Feb 16 11:17:11 CST 2020
endTime: Sun Feb 16 11:17:16 CST 2020
beginTime: Sun Feb 16 11:17:16 CST 2020
endTime: Sun Feb 16 11:17:21 CST 2020
beginTime: Sun Feb 16 11:17:21 CST 2020
endTime: Sun Feb 16 11:17:26 CST 2020
beginTime: Sun Feb 16 11:17:26 CST 2020
endTime: Sun Feb 16 11:17:31 CST 2020
beginTime: Sun Feb 16 11:17:31 CST 2020
endTime: Sun Feb 16 11:17:36 CST 2020
beginTime: Sun Feb 16 11:17:36 CST 2020
目前任務執行時間大于等于間隔時間,任務執行後立即執行下一次任務。相當于連續執行了。
scheduleWithFixedDelay
public static void main(String[] args) {
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat(
"my-test-pool-%d").build();
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1, threadFactory);
Date startTime = new Date();
System.out.println("startTime: " + startTime.toString());
scheduledExecutorService.scheduleWithFixedDelay(() -> {
System.out.println("beginTime: " + new Date().toString());
try {
Thread.sleep(5 * 1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("endTime: " + new Date().toString());
}, 2, 3, TimeUnit.SECONDS);
}
startTime: Sun Feb 16 11:27:26 CST 2020
beginTime: Sun Feb 16 11:27:28 CST 2020
endTime: Sun Feb 16 11:27:33 CST 2020
beginTime: Sun Feb 16 11:27:36 CST 2020
endTime: Sun Feb 16 11:27:41 CST 2020
beginTime: Sun Feb 16 11:27:44 CST 2020
endTime: Sun Feb 16 11:27:49 CST 2020
beginTime: Sun Feb 16 11:27:52 CST 2020
每當上次任務執行完畢後,間隔一段時間執行。不管目前任務執行時間大于、等于還是小于間隔時間,執行效果都是一樣的。
常見的“坑”
關于定時線程池(定時任務scheduleAtFixedRate和延時任務scheduleWithFixedDelay),好多人認為設定好頻率(比如1Min),它會按照這個間隔按部就班的工作。但是,如果其中一次排程任務卡住的話,不僅這次排程失敗,而且整個線程池也會停在這次排程上。
如果run方法中抛出異常,而又沒有捕獲,會導緻整個定時任務卡住。建議在整個run方法中使用try...catch...fianlly...處理。
public static void main(String[] args) {
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat(
"my-test-pool-%d").build();
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1, threadFactory);
Date startTime = new Date();
System.out.println("startTime: " + startTime.toString());
scheduledExecutorService.scheduleAtFixedRate(() -> {
System.out.println("beginTime: " + new Date().toString());
try {
Thread.sleep(5 * 1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("endTime: " + new Date().toString());
throw new NullPointerException();
}, 2, 3, TimeUnit.SECONDS);
}
