摘要:的類圖如下實現了接口,繼承了接口,所以首先是一個線程池,然后除了具有線程池的功能,它還有定時和周期性執行任務的功能。
在現實世界里,我們總是免不了要定期去做一件事情(比如上課)—— 在計算機的世界里,更是如此。比如我們手機每天叫我們起床的電子鬧鐘,某些網站會定期向我們發送一些推薦相關的郵件,集群中我們需要每隔一定時間檢查是否有機器宕機等。
在 使用線程池 中已經介紹,JDK 1.5 時,標準類庫添加了對線程池的支持,然后在線程池核心實現 ThreadPoolExecutor 的基礎上,實現了 ScheduledThreadPoolExecutor,作為可以 定時和周期性執行任務 的線程池。ScheduledThreadPoolExecutor 的類圖如下:
ScheduledThreadPoolExecutor 實現了 ScheduledExecutorService 接口,ScheduledExecutorService 繼承了 ExecutorService 接口,所以首先 ScheduledThreadPoolExecutor 是一個 ExecutorService (線程池),然后除了具有線程池的功能,它還有定時和周期性執行任務的功能。ScheduledExecutorService 除了從 ExecutorService 繼承的方法外,還包括如下四個方法:
第一個 Schedule 方法:
delay 指定的時間后,執行指定的 Runnable 任務,可以通過返回的 ScheduledFuture> 與該任務進行交互。
第二個 Schedule 方法:
delay 指定的時間后,執行指定的 Callable
(ScheduledFuture 接口 繼承自 Future 接口,所以 ScheduledFuture 和任務的交互方式與 Future 一致。所以通過ScheduledFuture,可以 判斷定時任務是否已經完成,獲得定時任務的返回值,或者取消任務等)
scheduleAtFixedRate 方法:
initialDelay 指定的時間后,開始按周期 period 執行指定的 Runnable 任務。
假設調用該方法后的時間點為 0,那么第一次執行任務的時間點為 initialDelay,第二次為 initialDelay + period,第三次為 initialDelay + period + period,以此類推。
scheduleWithFixedDelay 方法:
initialDelay 指定的時間后,開始按指定的 delay 延期性的執行指定的 Runnable 任務。
假設調用該方法后的時間點為 0,每次任務需要耗時 T(i)(i 為第幾次執行任務),那么第一次執行任務的時間點為 initialDelay,第一次完成任務的時間點為 initialDelay + T(1),則第二次執行任務的時間點為 initialDelay + T(1) + delay;第二次完成任務的時間點為 initialDelay + (T(1) + delay) + T(2),所以第三次執行任務的時間點為 initialDelay + T(1) + delay + T(2) + delay,以此類推。
我們來實踐下 ScheduledThreadPoolExecutor 的 scheduleAtFixedRate 方法:
public class ScheduledExecutorServiceTest { public static void main(String[] args) throws Exception { ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(); TimerTask timerTask = new TimerTask(2000); // 任務需要 2000 ms 才能執行完畢 System.out.printf("起始時間:%s ", new SimpleDateFormat("HH:mm:ss").format(new Date())); // 延時 1 秒后,按 3 秒的周期執行任務 timer.scheduleAtFixedRate(timerTask, 1000, 3000, TimeUnit.MILLISECONDS); } private static class TimerTask implements Runnable { private final int sleepTime; private final SimpleDateFormat dateFormat; public TimerTask(int sleepTime) { this.sleepTime = sleepTime; dateFormat = new SimpleDateFormat("HH:mm:ss"); } @Override public void run() { System.out.println("任務開始,當前時間:" + dateFormat.format(new Date())); try { System.out.println("模擬任務運行..."); Thread.sleep(sleepTime); } catch (InterruptedException ex) { ex.printStackTrace(System.err); } System.out.println("任務結束,當前時間:" + dateFormat.format(new Date())); System.out.println(); } } }
運行結果:
可以看到運行結果完全符合預期 —— 延時 1 秒后,每隔 3 秒執行一次任務。
上面是任務的運行時間小于周期時間的情況 —— 那如果任務運行的時間大于給定的執行周期呢?(比如任務運行需要 3 s,但是我們指定的周期為 2 s)
修改 main 方法:
public static void main(String[] args) throws Exception { ScheduledExecutorService timer = Executors.newScheduledThreadPool(2); TimerTask timerTask = new TimerTask(3000); // 每個任務需要 3000 ms 才能執行完畢 System.out.printf("起始時間:%s ", new SimpleDateFormat("HH:mm:ss").format(new Date())); timer.scheduleAtFixedRate(timerTask, 1000, 2000, TimeUnit.MILLISECONDS); }
運行結果:
可以看到此時雖然我們指定的周期為 2 s,但是因為任務的運行就需要 3 s(超過周期),所以這種情況下 scheduleAtFixedRate 的處理方式為 上一次任務剛完成,則緊接著立即運行下一次任務,而不是使用線程池中的空閑線程來運行任務以維護 2 秒這個周期 —— 由此可見,每個定時任務在 ScheduledThreadPoolExecutor 中,都是串行運行的,即下一次運行任務一定在上一次任務結束之后。
(scheduleWithFixedDelay 方法 的使用也十分簡單,請有興趣的讀者自己實踐)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/66448.html
摘要:目標線程由運行狀態轉換為就緒狀態,也就是讓出執行權限,讓其他線程得以優先執行,但其他線程能否優先執行時未知的。函數的官方解釋是意思是使調用該函數的線程讓出執行時間給其他已就緒狀態的線程。 線程允許在同一個進程中同時存在多個程序控制流,即通過線程可以實現同時處理多個任務的功能。線程會共享進程范圍內的資源,例如內存句柄和文件句柄,但每個線程都有各自的程序計數器、棧以及局部變量。 多線程的實...
摘要:也是自帶的一個基于線程池設計的定時任務類。其每個調度任務都會分配到線程池中的一個線程執行,所以其任務是并發執行的,互不影響。 原創不易,如需轉載,請注明出處https://www.cnblogs.com/baixianlong/p/10659045.html,否則將追究法律責任?。?! 一、在JAVA開發領域,目前可以通過以下幾種方式進行定時任務 1、單機部署模式 Timer:jdk中...
摘要:創建線程的方式方式一將類聲明為的子類。將該線程標記為守護線程或用戶線程。其中方法隱含的線程為父線程?;謴途€程,已過時。等待該線程銷毀終止。更多的使當前線程在鎖存器倒計數至零之前一直等待,除非線 知識體系圖: showImg(https://segmentfault.com/img/bVbef6v?w=1280&h=960); 1、線程是什么? 線程是進程中獨立運行的子任務。 2、創建線...
摘要:有三種狀態運行關閉終止。類類,提供了一系列工廠方法用于創建線程池,返回的線程池都實現了接口。線程池的大小一旦達到最大值就會保持不變,在提交新任務,任務將會進入等待隊列中等待。此線程池支持定時以及周期性執行任務的需求。 這是java高并發系列第19篇文章。 本文主要內容 介紹Executor框架相關內容 介紹Executor 介紹ExecutorService 介紹線程池ThreadP...
閱讀 2045·2023-04-26 02:23
閱讀 1789·2021-09-03 10:30
閱讀 1351·2019-08-30 15:43
閱讀 1191·2019-08-29 16:29
閱讀 530·2019-08-29 12:28
閱讀 2332·2019-08-26 12:13
閱讀 2169·2019-08-26 12:01
閱讀 2400·2019-08-26 11:56