定时器Timer与TimerTask的使用
一:簡介
在JDK類庫中Timer主要負責計劃任務的功能,也就是在指定時間執行某一任務,執行時候會在主線程之外起一個單獨的線程執行指定的任務。該類主要是設置任務計劃,但封裝的類是TimerTask類。
TimerTask是一個實現了Runnable接口的抽象類,代表一個可被執行的任務,執行任務的代碼要放在其子類中(TimerTask是抽象類)。
二:Timer整體類圖
TimerTask類:主要為定時任務的具體內容。 Timer類中含有3個類:Timer、TimerThread、TaskQueue。 Timer類主要是設置定時任務,配置用戶期望的任務執行時間、執行次數、執行內容 TimerThread類為Thread的擴展類,會一直從TaskQueue中獲取下標為1的TimerTask進行執行。并根據該TimerTask是否需要重復執行來決定是否放回到TaskQueue中。 TaskQueue中存放一些列將要執行的TimerTask,以數組的形式存放,下標約小(注:下標為0不處理,即使用的最小下標為1),則表明優先級越高。 public class Timer {//默認給線程命名:"Timer-" + serialNumber()public Timer() {this("Timer-" + serialNumber());}//指定Timer的名字public Timer(String name) {thread.setName(name);thread.start();}//isDaemon:是否為守護線程public Timer(boolean isDaemon) {this("Timer-" + serialNumber(), isDaemon);}//給定線程名字,守護線程與否public Timer(String name, boolean isDaemon) {thread.setName(name);//setDaemon是指定線程是否為守護線程,true是守護線程,當主線程退出, 守護線程退出thread.setDaemon(isDaemon);thread.start();} }//TimerThread類 繼承Thread class TimerThread extends Thread{private void mainLoop() {......//每次執行下標為1的TimerTasktask = queue.getMin();......} }//TaskQueue 類 class TaskQueue {//TaskQueue 中存儲TimerTaskprivate TimerTask[] queue = new TimerTask[128];//返回數組中下標1的TimerTaskTimerTask getMin() {return queue[1];} }三:Timer常用方法
1.Timer 類void schedule(TimerTask task, Date time)方法
1.task是定時任務,time是task任務執行時間.如果time時間早于當前則立即執行,否則在time時間執行。 2.task只執行一次,且執行完Timer線程任務不結束,因為Timer不是守護線程,Timer timer = new Timer(true); 是指定Timer 為守護線程,當task執行結束后,Timer 線程會立即結束。 3.Timer 可以執行多個定時任務,TimerTask 將會按照隊列的方式一個一個被執行,如果前面的任務耗時長,后面的任務執行時間將會相應的延后。 public class TimerDemo {//指定Timer為守護線程,run方法結束Timer線程會結束。private static Timer timer = new Timer(true);//TimerTask 具體的定時任務static public class MyTask extends TimerTask {@Overridepublic void run() {System.out.println("已運行,時間為:" + new Date());}}public static void main(String[] args) {//創建定時任務MyTask myTask = new MyTask();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//早于當前時間,定時任務會立即執行String dateString = "2020-06-01 09:56:00";try {Date taskDate = sdf.parse(dateString);//啟動定時任務timer.schedule(myTask,taskDate);} catch (Exception e) {e.printStackTrace();}} } 已運行,時間為:Wed Jul 01 14:48:06 CST 20202.Timer 類void schedule(TimerTask task, Date firstTime, long period)方法
TimerTask任務在指定 firstTime任務之后,周期性每隔period時間,無限期循環的執行某一任務。3.TimerTask 類boolean cancel()方法
TimerTask 類boolean cancel()方法,是將自身任務從任務隊列中移除。
public class TimerDemo {private static Timer timer = new Timer();static public class MyTaskA extends TimerTask {@Overridepublic void run() {//只輸出一次,MyTaskA 任務將會移除System.out.println("MyTaskA已運行,時間為:" + new Date());//執行TimerTask的cancel方法,將自身任務從隊列中移除this.cancel();}}static public class MyTaskB extends TimerTask {@Overridepublic void run() {//移除MyTaskA任務,MyTaskB 任務不受影響System.out.println("MyTaskB已運行,時間為:" + new Date());}}public static void main(String[] args) {MyTaskA myTaskA = new MyTaskA();MyTaskB myTaskB = new MyTaskB();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String dateString = "2020-07-01 15:19:00";try {Date taskDate = sdf.parse(dateString);timer.schedule(myTaskA,taskDate,2000);timer.schedule(myTaskB,taskDate,2000);} catch (Exception e) {e.printStackTrace();}} } MyTaskA已運行,時間為:Wed Jul 01 15:24:47 CST 2020 MyTaskB已運行,時間為:Wed Jul 01 15:24:47 CST 2020 MyTaskB已運行,時間為:Wed Jul 01 15:24:49 CST 2020 MyTaskB已運行,時間為:Wed Jul 01 15:24:51 CST 2020 MyTaskB已運行,時間為:Wed Jul 01 15:24:53 CST 2020 MyTaskB已運行,時間為:Wed Jul 01 15:24:55 CST 2020 MyTaskB已運行,時間為:Wed Jul 01 15:24:57 CST 2020 MyTaskB已運行,時間為:Wed Jul 01 15:24:59 CST 20204.Timer 類void cancel()方法
Timer 類void cancel()方法與TimerTask 類boolean cancel()方法將自身任務從任務隊列中移除不同,它是將所有的任務都從隊列中移除。
public class TimerDemo {private static Timer timer = new Timer();static public class MyTaskA extends TimerTask {@Overridepublic void run() {System.out.println("MyTaskA已運行,時間為:" + new Date());//執行Timer類的cancel方法,將Timer中所有任務從隊列中移除timer.cancel();}}static public class MyTaskB extends TimerTask {@Overridepublic void run() {//MyTaskB也會被移除,因為MyTaskA與MyTaskB是隊列執行,先執行MyTaskA再執行MyTaskB//MyTaskA中走了timer.cancel(),所以MyTaskB不會執行System.out.println("MyTaskB已運行,時間為:" + new Date());}}public static void main(String[] args) {MyTaskA myTaskA = new MyTaskA();MyTaskB myTaskB = new MyTaskB();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String dateString = "2020-07-01 15:19:00";try {Date taskDate = sdf.parse(dateString);timer.schedule(myTaskA,taskDate,2000);timer.schedule(myTaskB,taskDate,2000);} catch (Exception e) {e.printStackTrace();}} } MyTaskA已運行,時間為:Wed Jul 01 16:20:48 CST 2020源碼:
public void cancel() {synchronized(queue) {thread.newTasksMayBeScheduled = false;queue.clear();queue.notify(); // In case queue was already empty.}}執行cancel需要搶占queue鎖,如果搶不到,則TimerTask 任務會繼續執行。
5.Timer 類 void schedule(TimerTask task, long delay)方法
該方法以schedule(TimerTask task, long delay)方法的執行時間為基準,在此時間上延遲指定的毫秒數delay后執行一次TimerTask 任務。
6.Timer 類 void schedule(TimerTask task, long delay, long period)方法
該方法以schedule(TimerTask task, long delay, long period)方法的執行時間為基準,在此時間上延遲指定的毫秒數delay后,執行TimerTask 任務,之后間隔period毫秒無限循環執行TimerTask 任務。
7.Timer 類void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)方法
TimerTask任務在指定 firstTime任務之后,周期性每隔period時間,無限期循環的執行某一任務。
四:重點:scheduleAtFixedRate(TimerTask task, Date firstTime, long period)與 schedule(TimerTask task, Date firstTime, long period)方法區別
1.相同點:兩個方法都是按照順序執行,無線程安全問題 2.任務不延時相同點:如果任務執行時間小于任務時間間隔,則第二次任務的開始時間是任務開始時間+period 3.任務延時相同點:如果任務執行時間大于任務時間間隔,導致第二次任務開始時候,上一個任務還未結束,則第二次任務的開始時間是在第一次任務結束時候立即執行。scheduleAtFixedRate方法與schedule方法的追趕性問題
scheduleAtFixedRate方法具有追趕性!!!!如果計劃執行時間早于當前時間,執行scheduleAtFixedRate方法后立即執行定時任務,根據任務間隔時間與當前時間減去計劃執行時間,補上之前少執行的任務。
schedule方法不具有追趕性。!!!!
由上述執行結果可知,在Thu Jul 02 14:34:38 CST 2020啟動定時任務后,沒有間隔3s再執行下一次任務,而是任務結束就立即執行,這是因為任務計劃執行時間早于當前時間,需要將這期間沒有執行的任務補上。
五: 總結
java中可以使用定時任務的功能,針對不同的定時任務可以根據不同的API進行處理,從本質來說改技術仍然屬于多線程,基于多線程實現,不管用再多的框架實現定時器功能,請不要忘了這事java基礎,框架實現的基礎。
總結
以上是生活随笔為你收集整理的定时器Timer与TimerTask的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 推荐两个在线代理服务器
- 下一篇: 文档词频矩阵_对论文“从词向量到文档距离