亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術(shù)文章
文章詳情頁

Java簡單實現(xiàn)定時器

瀏覽:20日期:2022-08-13 15:13:48

本文實例為大家分享了Java簡單實現(xiàn)定時器的具體代碼,供大家參考,具體內(nèi)容如下

一、定時器

定時器相當于一個任務管理器。有些任務可能現(xiàn)在執(zhí)行, 有些任務可能過1個小時,甚至很久才會執(zhí)行。定時器就是對這些任務進行管理監(jiān)視, 如果一個任務執(zhí)行時間到了,定時器就會將這個任務執(zhí)行。 保證所有的任務都會在合適的時間執(zhí)行。

二、定時器的實現(xiàn)

對于定時器的實現(xiàn),我們可以劃分為3個部分。

1、 使用一個Task類描述每一個任務(里面包含任務的執(zhí)行方法, 定時時間)。2、 使用優(yōu)先級隊列管理這些任務類。

2.1 我們都知道優(yōu)先級隊列底層實現(xiàn)是堆(以小根堆為例), 堆頂?shù)脑厥撬械脑氐淖钚≈怠?我們以任務的定時時間為比較原則構(gòu)建, 這樣就可以保證堆頂元素的任務執(zhí)行時間是最短的(這樣的實現(xiàn),我們需要在Task類內(nèi)部定義比較規(guī)則-即重寫Comparable接口的CompareTo方法)。

2.2 當一個任務執(zhí)行完畢, 就會從優(yōu)先級隊列取出poll掉, 然后內(nèi)部重新組織保證新的堆頂元素是定時時間最短的。

2.3 如果說堆頂?shù)娜蝿斩〞r時間還沒有到達(當然后續(xù)的任務定時時間肯定會更長,不會被執(zhí)行)

3、使用一個線程循環(huán)掃描優(yōu)先級隊列, 相當于一個監(jiān)控線程,循環(huán)判斷堆頂任務是否滿足執(zhí)行時間。

三、定時器的組成

1、制定任務類Task

Task類包含任務的 執(zhí)行方法 和 定時時間。

1.1 執(zhí)行方法我采用封裝Runnable中run方法實現(xiàn), 這樣做是為了后續(xù)添加任務時方便寫執(zhí)行邏輯。1.2 定時時間就是long類型的變量1.3 制定比較規(guī)則, 后續(xù)優(yōu)先級隊列中存放的是Task對象(而在內(nèi)部構(gòu)建時,需要比較兩個Task對象的),對于對象的比較, 我們以對象的定時時間為規(guī)則, 制定小根堆。

static class Task implements Comparable<Task>{//Runnable類中有一個run方法, 通過這個方法實現(xiàn)任務的執(zhí)行private Runnable command;//time表示執(zhí)行的時間private long time;//構(gòu)造方法public Task(Runnable command, long time) { this.command = command; this.time = System.currentTimeMillis() + time; //將時間轉(zhuǎn)化為絕對時間}//執(zhí)行任務的邏輯public void run() { command.run();}//定義比較方法 - 方便后續(xù)的優(yōu)先級隊列構(gòu)建@Overridepublic int compareTo(Task o) { return (int)(this.time - o.time);} }

2、監(jiān)管線程&定時器對象Timer

監(jiān)管線程Worker中包含優(yōu)先級隊列(小根堆)queue 和 循環(huán)監(jiān)管的流程。

Timer對象封裝了監(jiān)管線程Woker 和 任務的添加方法schedule()

關(guān)于監(jiān)管線程的優(yōu)化

2.1 循環(huán)監(jiān)控存在一個弊端,那就是一直循環(huán)判斷, 占用CPU資源。(假如堆首任務的執(zhí)行是1小時后, 再次期間監(jiān)管線程會跑1小時循環(huán)判斷。)

解決方法: 可以通過線程阻塞和喚醒來解決。在下面代碼有詳細注釋和實現(xiàn)。

2.1.1 如果任務1小時后執(zhí)行, 我們讓監(jiān)管線程wait(1小時), 但在此期間如果有新的任務添加進來(可能新的任務需要等30分鐘就可以執(zhí)行,堆首元素發(fā)生變化) ,這時需要喚醒監(jiān)管線程來重新判斷。(由于wait和notify方法不在用一個類中實現(xiàn), 我們通過一個Object(mailBox)來阻塞、喚醒)

//檢測線程, 繼承Thread類,重寫內(nèi)部run方法,屬于線程的創(chuàng)建方法之一。 static class Worker extends Thread { //優(yōu)先級隊列 - JUC包里面private PriorityBlockingQueue<Task> queue = null;//為了對監(jiān)管線程進行阻塞和喚醒,采用同一對象private Object mailBox = null; //構(gòu)造函數(shù)public Worker(PriorityBlockingQueue<Task> queue, Object mailBox) { this.queue = queue; this.mailBox = mailBox;}@Overridepublic void run() { //實現(xiàn)具體的執(zhí)行邏輯 while(true) {try { //1、取優(yōu)先級隊列的隊首元素 Task task = queue.peek(); //2、比較隊首的元素的時間是否大于當前時間 if(task == null) {continue; } long curTime = System.currentTimeMillis(); if(task.time > curTime) {//時間還沒有到, 由于取出了任務, 需要重新放置回去//優(yōu)化1: 空循環(huán)等待 - wait(time) 讓線程休眠time時間,然后在執(zhí)行// 如果在等待期間有新的任務添加, 這個時候我們喚醒線程, 繼續(xù)判斷(因為存在新的時間過短需要立即執(zhí)行)// 這個只需要添加一個新任務時, 喚醒即可//優(yōu)化2: 訪問隊首元素而不是取出, 防止無所謂的刪除、插入。(維護優(yōu)先級隊列是有消耗的)long gapTime = task.time - curTime;synchronized (mailBox) { mailBox.wait(gapTime);} } else {//直接執(zhí)行//如果執(zhí)行到了, 則會刪除頭部元素, 調(diào)用任務的執(zhí)行過程。task = queue.take();task.run(); }}catch(InterruptedException e) { e.printStackTrace(); break;} }} } //定時器簡單實現(xiàn) static class Timer {//定時器的實現(xiàn)步驟//1、用一個類描述任務//2、用優(yōu)先級隊列管理這些任務, 比較方法通過任務的制定時間,每次取隊首元素// 隊首元素是執(zhí)行時間最近的private PriorityBlockingQueue<Task> queue = new PriorityBlockingQueue<>();//3、用一個線程來循環(huán)掃描當前的阻塞隊列,判斷隊首的執(zhí)行時間, 如果執(zhí)行時間到了,那就執(zhí)行。//4、創(chuàng)建一個Object對象,用于設置線程阻塞使用的, 存在線程阻塞, 添加任務時喚醒的操作private Object mailBox = new Object();//構(gòu)造函數(shù)public Timer() { //創(chuàng)建線程 Worker worker = new Worker(queue, mailBox); worker.start();}//4、提供一個方法, 讓調(diào)用者能夠把任務安排起來public void schedule(Runnable command, long time) { Task task = new Task(command, time); queue.put(task); synchronized (mailBox) {mailBox.notify(); }} }

3、測試代碼

其中添加了4個任務, 分別是2s、5s、7s、10s后執(zhí)行。

public static void main(String[] args) {Timer timer = new Timer();timer.schedule(new Runnable() { @Override public void run() {System.out.println('郝夢武一號任務執(zhí)行, 執(zhí)行代號:閃電; 定時時間:2s'); }}, 2000);timer.schedule(new Runnable() { @Override public void run() {System.out.println('郝夢武二號任務執(zhí)行, 執(zhí)行代號:暴風; 定時時間:5s'); }}, 5000);timer.schedule(new Runnable() { @Override public void run() {System.out.println('郝夢武三號任務執(zhí)行, 執(zhí)行代號:狂風; 定時時間:7s'); }}, 7000);timer.schedule(new Runnable() { @Override public void run() {System.out.println('郝夢武三號任務執(zhí)行, 執(zhí)行代號:地震; 定時時間:10s'); }}, 10000); }

4、測試結(jié)果

Java簡單實現(xiàn)定時器

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標簽: Java
相關(guān)文章:
主站蜘蛛池模板: 国产精品高清一区二区三区不卡 | 女人被狂躁的视频免费一一 | 91桃色视频在线观看 | 美国一级大黄一片免费的网站 | 九九国产在线观看 | 小明免费视频一区二区 | 国产精品情侣 | 在线看国产视频 | 麻豆a| 尤物在线免费视频 | 欧美黄色免费在线观看 | 网友自拍视频精品区 | 午夜三级在线 | 精品日韩在线 | 日韩综合久久 | 97香蕉超级碰碰碰久久兔费 | 欧美一级毛片欧美大尺度一级毛片 | 久久综合久久综合久久 | 国产精品久久久久久影视 | 国产成人三级经典中文 | 成年午夜性视频免费播放 | 欧美5g影院天天爽天天看 | 国产小视频免费观看 | 美女xx网站 | 日本一级级特黄特色大片 | 免费香蕉视频国产在线看 | 国产精品久久毛片 | 国产亚洲视频网站 | 一级片在线观看 | 国产精品精品视频 | 泰国一级淫片免费看 | 欧美1区二区三区公司 | 91在线观| 久久夏同学国产免费观看 | 亚洲你xx我xx网站 | 久久国产自偷自偷免 | 在线观看香蕉免费啪在线观看 | 91精品日本久久久久久牛牛 | 亚洲欧美日韩中文综合v日本 | xxxx免费国产在线视频 | 日本不卡一区二区三区视频 |