亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

java Timer(定時調用、實現固定時間執行)

2019-11-15 01:02:47
字體:
來源:轉載
供稿:網友
java Timer(定時調用、實現固定時間執行)

  最近需要用到定時調用的功能。可以通過java的Timer類來進行定時調用,下面是有關Timer的一些相關知識。

  其實就Timer來講就是一個調度器,而TimerTask呢只是一個實現了run方法的一個類,而具體的TimerTask需要由你自己來實現,例如這樣:

Timer timer = new Timer();timer.schedule(new TimerTask() {        public void run() {            System.out.

  這里直接實現一個TimerTask(當然,你可以實現多個TimerTask,多個TimerTask可以被一個Timer會被分配到多個 Timer中被調度,后面會說到Timer的實現機制就是說內部的調度機制),然后編寫run方法,20s后開始執行,每秒執行一次,當然你通過一個 timer對象來操作多個timerTask,其實timerTask本身沒什么意義,只是和timer集合操作的一個對象,實現它就必然有對應的run 方法,以被調用,他甚至于根本不需要實現Runnable,因為這樣往往混淆視聽了,為什么呢?也是本文要說的重點。

  在說到timer的原理時,我們先看看Timer里面的一些常見方法:

1、這個方法是調度一個task,經過delay(ms)后開始進行調度,僅僅調度一次。

    public void schedule(TimerTask task, long delay)

2、在指定的時間點time上調度一次。

public void schedule(TimerTask task, Date time)

3、這個方法是調度一個task,在delay(ms)后開始調度,每次調度完后,最少等待period(ms)后才開始調度。
public void schedule(TimerTask task, long delay, long period)

4、和上一個方法類似,唯一的區別就是傳入的第二個參數為第一次調度的時間。
public void schedule(TimerTask task, Date firstTime, long period)

5、調度一個task,在delay(ms)后開始調度,然后每經過period(ms)再次調度,貌似和方法:schedule是一樣的,其實不然,后面你會根據
源碼看到,schedule在計算下一次執行的時間的時候,是通過當前時間(在任務執行前得到) + 時間片,而scheduleAtFixedRate方法是通過當前需要執行的時間(也就是計算出現在應該執行的時間)+ 時間片,前者是運行的實際時間,而后者是理論時間點,例如:schedule時間片是5s,那么理論上會在5、10、15、20這些時間片被調度,但是如果由于某些CPU征用導致未被調度,假如等到第8s才被第一次調度,那么schedule方法計算出來的下一次時間應該是第13s而不是第10s,這樣有可能下次就越到20s后而被少調度一次或多次,而scheduleAtFixedRate方法就是每次理論計算出下一次需要調度的時間用以排序,若第8s被調度,那么計算出應該是第10s,所以它距離當前時間是2s,那么再調度隊列排序中,會被優先調度,那么就盡量減少漏掉調度的情況。
public void scheduleAtFixedRate(TimerTask task, long delay, long period)

6、方法同上,唯一的區別就是第一次調度時間設置為一個Date時間,而不是當前時間的一個時間片,我們在源碼中會詳細說明這些內容。
public void scheduleAtFixedRate(TimerTask task, Date firstTime,long period)


源碼部分首先看Timer的構造方法有幾種:構造方法1:無參構造方法,簡單通過Tiemer為前綴構造一個線程名稱:
public Timer() {    this("Timer-" + serialNumber());}

  創建的線程不為主線程,則主線程結束后,timer自動結束,而無需使用cancel來完成對timer的結束。

構造方法2:傳入了是否為后臺線程,后臺線程當且僅當進程結束時,自動注銷掉。
public Timer(boolean isDaemon) {    this("Timer-" + serialNumber(), isDaemon);}

  另外兩個構造方法負責傳入名稱和將timer啟動:

public Timer(String name, boolean isDaemon) {      thread.setName(name);      thread.setDaemon(isDaemon);      thread.start();  }

  這里有一個thread,這個thread很明顯是一個線程,被包裝在了Timer類中,我們看下這個thread的定義是:

private TimerThread thread = new TimerThread(queue);

  而定義TimerThread部分的是:
而定義TimerThread部分的是:

  看到這里知道了,Timer內部包裝了一個線程,用來做獨立于外部線程的調度,而TimerThread是一個default類型的,默認情況下是引用不到的,是被Timer自己所使用的。

  接下來看下有那些屬性  除了上面提到的thread,還有一個很重要的屬性是:
private TaskQueue queue = new TaskQueue();

  看名字就知道是一個隊列,隊列里面可以先猜猜看是什么,那么大概應該是我要調度的任務吧,先記錄下了,接下來繼續向下看:

  里面還有一個屬性是:threadReaper, 它是Object類型,只是重寫了finalize方法而已,是為了垃圾回收的時候,將相應的信息回收掉,做GC的回補,也就是當timer線程由于某種 原因死掉了,而未被cancel,里面的隊列中的信息需要清空掉,不過我們通常是不會考慮這個方法的,所以知道java寫這個方法是干什么的就行了?! 〗酉聛砜凑{度方法的實現:  對于上面6個調度方法,我們不做一一列舉,為什么等下你就知道了:

  來看下方法:

public void schedule(TimerTask task, long delay)

  的源碼如下:

1 public void schedule(TimerTask task, long delay) {2        if (delay < 0)3            throw new IllegalArgumentException("Negative delay.");4        sched(task, System.currentTimeMillis()+delay, 0);5    }

  這里調用了另一個方法,將task傳入,第一個參數傳入System.currentTimeMillis()+delay可見為第一次需要執行的時間的 時間點了(如果傳入Date,就是對象.getTime()即可,所以傳入Date的幾個方法就不用多說了),而第三個參數傳入了0,這里可以猜下要么是 時間片,要么是次數啥的,不過等會就知道是什么了;另外關于方法:sched的內容我們不著急去看他,先看下重載的方法中是如何做的

  再看看方法:
public void schedule(TimerTask task, long delay,long period)

  源碼為:

public void schedule(TimerTask task, long delay, long period) {        if (delay < 0)            throw new IllegalArgumentException("Negative delay.");        if (period <= 0)            throw new IllegalArgumentException("Non-positive period.");        sched(task, System.currentTimeMillis()+delay, -period);    }

  看來也調用了方法sched來完成調度,和上面的方法唯一的調度時候的區別是增加了傳入的period,而第一個傳入的是0,所以確定這個參數為時間片, 而不是次數,注意這個里的period加了一個負數,也就是取反,也就是我們開始傳入1000,在調用sched的時候會變成-1000,其實最終閱讀完 源碼后你會發現這個算是老外對于一種數字的理解,而并非有什么特殊的意義,所以閱讀源碼的時候也有這些困難所在。

  最后再看個方法是:
public void scheduleAtFixedRate(TimerTasktask,long delay,long period)

  源碼為:

public void scheduleAtFixedRate(TimerTask task, long delay, long period) {       if (delay < 0)           throw new IllegalArgumentException("Negative delay.");       if (period <= 0)           throw new IllegalArgumentException("Non-positive period.");       sched(task, System.currentTimeMillis()+delay, period);   }

  唯一的區別就是在period沒有取反,其實你最終閱讀完源碼,上面的取反沒有什么特殊的意義,老外不想增加一個參數來表示 scheduleAtFixedRate,而scheduleAtFixedRate和schedule的大部分邏輯代碼一致,因此用了參數的范圍來作為 區分方法,也就是當你傳入的參數不是正數的時候,你調用schedule方法正好是得到scheduleAtFixedRate的功能,而調用 scheduleAtFixedRate方法的時候得到的正好是schedule方法的功能,呵呵,這些討論沒什么意義,討論實質和重點:

  來看sched方法的實現體:

private void sched(TimerTask task, long time, long period) {        if (time < 0)            throw new IllegalArgumentException("Illegal execution time.");         synchronized(queue) {            if (!thread.newTasksMayBeScheduled)                throw new IllegalStateException("Timer already cancelled.");             synchronized(task.lock) {                if (task.state != TimerTask.VIRGIN)                    throw new IllegalStateException(                        "Task already scheduled or cancelled");                task.nextExecutionTime = time;                task.period = period;                task.state = TimerTask.SCHEDULED;            }             queue.add(task);            if (queue.getMin() == task)                queue.notify();        }    }

  queue為一個隊列,我們先不看他數據結構,看到他在做這個操作的時候,發生了同步,所以在timer級別,這個是線程安全的,最后將task相關的參數賦值,主要包含nextExecutionTime(下一次執行時間),period(時間片),state(狀態),然后將它放入queue隊列中,做一次notify操作,為什么要做notify操作呢?看了后面的代碼你就知道了。

  簡言之,這里就是講task放入隊列queue的過程,此時,你可能對queue的結構有些興趣,那么我們先來看看queue屬性的結構TaskQueue:

class TaskQueue {     private TimerTask[] queue = new TimerTask[128];     private int size = 0;

  可見,TaskQueue的結構很簡單,為一個數組,加一個size,有點像ArrayList,是不是長度就128呢,當然不 是,ArrayList可以擴容,它可以,只是會造成內存拷貝而已,所以一個Timer來講,只要內部的task個數不超過128是不會造成擴容的;內部 提供了add(TimerTask)、size()、getMin()、get(int)、removeMin()、quickRemove(int)、 rescheduleMin(long newTime)、isEmpty()、clear()、fixUp()、fixDown()、heapify();

   


實踐部分:1、通過繼承TimerTask的方式實現  必須重寫run方法.
public class MyTask extends TimerTask{    @Override    public void run()    {        SimpleDateFormat sdf = null;        sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");        System.out.println("當前時間:" + sdf.format(new Date()));            }    }

public class TestTask{    public static void main(String[] args)    {        Timer t = new Timer(); // 建立Timer對象        MyTask task = new MyTask(); //定義任務        t.schedule(task, 1000,2000);//設置任務的執行,1秒后開始,每2秒執行一次                Calendar cal = Calendar.getInstance();        cal.set(Calendar.MINUTE, 30);                t.schedule(task, cal.getTime() , 2000);            }}

2、通過匿名內部類實現

Timer timer = new Timer();          timer.scheduleAtFixedRate(new TimerTask() {                  public void run() {                                          System.out.println("abc");                  }          }, 1000 , 1000);

  致謝:感謝您的耐心閱讀!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产va免费精品高清在线观看| www.日韩.com| 国产精品一区二区久久精品| 亚洲图片在线综合| 国产精品爱久久久久久久| 91美女福利视频高清| 中文字幕日韩精品在线| 日本成人在线视频网址| 成人网在线观看| 久久久亚洲国产天美传媒修理工| 亚洲大尺度美女在线| 俺去了亚洲欧美日韩| 欧美成人精品在线播放| 亚洲美女免费精品视频在线观看| 欧美精品18videosex性欧美| 国产一区二区三区在线免费观看| 精品成人69xx.xyz| 欧美亚洲国产日本| 欧美日韩ab片| 国产精品极品尤物在线观看| 欧美理论电影在线观看| 亚洲成人网久久久| 久久国内精品一国内精品| 成人高清视频观看www| 国产视频亚洲精品| 最新亚洲国产精品| 久久亚洲春色中文字幕| 亚洲精品国产欧美| 日韩电影在线观看永久视频免费网站| 精品久久久久人成| 日本不卡视频在线播放| 亚洲精品成人久久电影| 欧美成人午夜剧场免费观看| 亚洲激情视频在线播放| 亚洲理论电影网| 欧美一级高清免费播放| 2018日韩中文字幕| 91国语精品自产拍在线观看性色| 亚洲精品乱码久久久久久按摩观| 欧美精品免费播放| 亚洲韩国青草视频| 国产一区二区三区视频在线观看| 精品人伦一区二区三区蜜桃网站| 97热精品视频官网| 欧美丰满少妇xxxx| 国产精品欧美日韩久久| 91精品在线一区| 精品国产美女在线| 日韩欧亚中文在线| 中文字幕亚洲第一| 成人免费网站在线| 精品色蜜蜜精品视频在线观看| 欧美精品久久久久久久| 色yeye香蕉凹凸一区二区av| 国产精品毛片a∨一区二区三区|国| 黑人狂躁日本妞一区二区三区| 国产精品国产三级国产aⅴ浪潮| 欧美午夜精品久久久久久浪潮| 欧美一区二区三区精品电影| 91精品国产乱码久久久久久久久| 亚洲午夜精品久久久久久性色| 亚洲国产精彩中文乱码av在线播放| 日韩精品在线视频美女| 国产精品免费久久久| 日韩电影中文字幕| 欧美区二区三区| 久久精品电影网站| 亚洲图片在线综合| 色播久久人人爽人人爽人人片视av| 亚洲激情视频网| 国产精品亚洲片夜色在线| 欧美黑人国产人伦爽爽爽| 国产精品福利小视频| 国产精品91久久久| 亚洲直播在线一区| 日韩一中文字幕| 永久555www成人免费| 国产精品一区二区女厕厕| 成人www视频在线观看| 欧美国产日韩xxxxx| 亚洲精品v欧美精品v日韩精品| 国产亚洲人成a一在线v站| 91精品中文在线| 欧美日韩亚洲91| 久久综合伊人77777蜜臀| 国产成人一区二区在线| 亚洲精品美女免费| 国产成人高清激情视频在线观看| 国产91色在线| 亚洲深夜福利视频| 自拍偷拍亚洲区| 国产欧美在线看| 日本aⅴ大伊香蕉精品视频| 国产福利视频一区| 日韩av一卡二卡| 日韩成人中文电影| 亚洲精品丝袜日韩| 国产精品专区第二| 成人午夜激情免费视频| 在线中文字幕日韩| 日韩在线观看免费高清| 亚洲欧美视频在线| 国产精品伦子伦免费视频| 成人免费视频97| 中文字幕一精品亚洲无线一区| 欧美三级欧美成人高清www| 狠狠干狠狠久久| 日韩av不卡电影| 欧美黑人视频一区| 国产精品丝袜久久久久久高清| 欧美中文在线免费| 久久精品视频在线播放| 97国产一区二区精品久久呦| 日韩欧美视频一区二区三区| 日韩网站免费观看高清| 亚洲综合最新在线| 操日韩av在线电影| 国产ts人妖一区二区三区| 欧美黑人巨大xxx极品| 国产精品成人久久久久| 欧美激情视频在线观看| 国产成人高清激情视频在线观看| 成人免费视频网址| 国产视频丨精品|在线观看| 精品久久久久久电影| 日韩精品欧美国产精品忘忧草| 亚洲视频视频在线| 日韩视频精品在线| 亚洲白虎美女被爆操| 日本人成精品视频在线| 日韩成人高清在线| 国产欧美日韩91| 日韩福利视频在线观看| 岛国精品视频在线播放| 中文字幕在线国产精品| 欧美午夜片欧美片在线观看| 欧美日韩在线影院| 日韩欧美一区二区在线| 久久国产天堂福利天堂| 欧洲美女免费图片一区| 久久精品国产综合| 中文字幕av一区中文字幕天堂| 亚洲第一天堂av| 日本精品免费观看| 国产精品视频一| 亚洲日韩中文字幕在线播放| 上原亚衣av一区二区三区| 日韩综合中文字幕| 亚洲深夜福利视频| 91精品视频免费| 欧美激情亚洲视频| 欧美日本精品在线| 国产免费一区二区三区在线能观看| 神马国产精品影院av| 中文字幕亚洲一区| 国产精品jizz在线观看麻豆| 成人国产在线视频| 日韩一区二区福利| 中文字幕在线观看日韩| 2019亚洲男人天堂| 琪琪第一精品导航| 欧美大荫蒂xxx| 最近2019年手机中文字幕| 国产精品一香蕉国产线看观看|