最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?Timer使用講解

 更新時間:2022年11月02日 10:23:48   作者:UnicornLien  
Timer是一種工具,線程用其安排以后在后臺線程中執(zhí)行的任務(wù)。可安排任務(wù)執(zhí)行一次,或者定期重復(fù)執(zhí)行,這篇文章主要介紹了Java?Timer使用講解,需要的朋友可以參考下

Timer 詳解

Timer 和 TimerTask 用于在后臺線程中調(diào)度任務(wù)的 java.util 類。 TimerTask 負責(zé)任務(wù)的執(zhí)行, Timer 負責(zé)任務(wù)的調(diào)度。

定時功能

Timer 提供了三種定時模式:

fixed delay
fixed rate

java.util包下提供了對定時任務(wù)的支持,涉及2個類:

  1. Timer:定時器類
  2. TimerTask:任務(wù)抽象類

使用該定時任務(wù)我們需要繼承TimerTask抽象類,覆蓋run方法編寫任務(wù)執(zhí)行代碼,并利用Timer定時器對TimerTask進行調(diào)度。

編寫一個任務(wù):

TimerTask task = new TimerTask() {
    @Override
    public void run() {
        System.out.println(DateUtil.formatNow() + " " + Thread.currentThread().getName() + " task run ");
    }
};

接著使用Timer對TimerTask進行調(diào)度,Timer提供了多種方法,可分為一次性任務(wù)和可重復(fù)執(zhí)行任務(wù)。

一、一次性任務(wù)

一次性任務(wù)是指Timer執(zhí)行一次之后,該任務(wù)后續(xù)不再執(zhí)行。

一次性任務(wù)包括2個方法,如下:

  1. voidschedule(TimerTasktask,longdelay):延遲delay毫秒后執(zhí)行一次task
  2. voidschedule(TimerTasktask,Datetime):在指定時間time執(zhí)行一次task,如果time過期,將會立即執(zhí)行

二、可重復(fù)執(zhí)行任務(wù)

可重復(fù)執(zhí)行任務(wù)是指,任務(wù)允許按照設(shè)定的規(guī)則重復(fù)執(zhí)行。

可重復(fù)執(zhí)行任務(wù)共有4個方法,分為固定延時 schedule和固定速率 scheduleAtFixedRate:

  1. voidschedule(TimerTasktask,longdelay,longperiod):延遲delay毫秒后執(zhí)行task,之后每隔period毫秒執(zhí)行一次task
  2. voidschedule(TimerTasktask,DatefirstTime,longperiod):在指定時間time執(zhí)行一次task,之后每隔period毫秒執(zhí)行一次task
  3. voidscheduleAtFixedRate(TimerTasktask,longdelay,longperiod):延遲delay毫秒后執(zhí)行task,之后每隔period毫秒執(zhí)行一次task
  4. voidscheduleAtFixedRate(TimerTasktask,DatefirstTime,longperiod):在指定時間time執(zhí)行一次task,之后每隔period毫秒執(zhí)行一次task

示例1:schedule方法,延遲delay毫秒后執(zhí)行task,之后每隔period毫秒執(zhí)行一次task

System.out.println("啟動于:" + DateUtil.formatNow());
Timer timer = new Timer("timer");
timer.schedule(task, 1000, 2000);

輸出:

啟動于:2022-10-31 10:05:15
2022-10-31 10:05:16 timer task run 
2022-10-31 10:05:18 timer task run 
2022-10-31 10:05:20 timer task run

示例2:schedule在指定時間time執(zhí)行一次task,之后每隔period毫秒執(zhí)行一次task

System.out.println("啟動于:" + DateUtil.formatNow());
Timer timer = new Timer("timer");
timer.schedule(task, DateUtil.parse("2022-10-31 10:07:00", DateUtil.YYYY_MM_DD_HH24_MM_SS), 2000);

輸出:

啟動于:2022-10-31 10:06:39
2022-10-31 10:07:00 timer task run 
2022-10-31 10:07:02 timer task run 
2022-10-31 10:07:04 timer task run 

固定延時 schedule 和 固定速率 scheduleAtFixedRate 在正常情況下看起來功能基本是一致的,區(qū)別在于當(dāng)任務(wù)耗時超出執(zhí)行時間間隔period,后續(xù)任務(wù)被延誤時,schedule和scheduleAtFixedRate的處理方式不同,后面介紹。

三、固定延時和固定速率區(qū)別(重點)

1. 介紹

由于Timer內(nèi)部僅維護一個線程來執(zhí)行所有任務(wù),所以當(dāng)前一個任務(wù)耗時過長,可能會導(dǎo)致后一個任務(wù)的執(zhí)行被延誤。

出現(xiàn)任務(wù)延誤的情況下,固定延時 schedule和 固定速率 scheduleAtFixedRate 的區(qū)別就在于,schedule會順延,而scheduleAtFixedRate會把延誤任務(wù)立馬補上。

在網(wǎng)上看到幾個非常恰當(dāng)?shù)睦?,貼上來加深理解。

例1:

暑假到了老師給schedule和scheduleAtFixedRate兩個同學(xué)布置作業(yè)。

老師要求學(xué)生暑假每天寫2頁,30天后完成作業(yè)。

這兩個學(xué)生每天按時完成作業(yè),直到第10天,出了意外,兩個學(xué)生出去旅游花了5天時間,這5天時間里兩個人都沒有做作業(yè)。任務(wù)被拖延了。

這時候兩個學(xué)生采取的策略就不同了:

schedule重新安排了任務(wù)時間,旅游回來的第一天做第11天的任務(wù),第二天做第12天的任務(wù),最后完成任務(wù)花了35天。

scheduleAtFixedRate是個守時的學(xué)生,她總想按時完成老師的任務(wù),于是在旅游回來的第一天把之前5天欠下的任務(wù)以及第16天當(dāng)天的任務(wù)全部完成了,之后還是按照老師的原安排完成作業(yè),最后完成任務(wù)花了30天。

例2:

固定速率就好比你今天加班到很晚,但是到了第二天還必須準點到公司上班,如果你一不小心加班到了第二天早上 9 點,你就連休息的時間都沒有了。

而固定時延的意思是你必須睡夠 8 個小時再過來上班,如果你加班到凌晨 6 點,那就可以下午過來上班了。

固定速率強調(diào)準點,固定時延強調(diào)間隔。

如果任務(wù)必須每天準點調(diào)度,那就應(yīng)該使用固定速率調(diào)度,并且要確保每個任務(wù)執(zhí)行時間不要太長,避免超過period間隔。

如果任務(wù)需要每隔幾分鐘跑一次,那就使用固定時延調(diào)度,它不是很在乎單個任務(wù)要跑多長時間。

我們來模擬一下這個情況。

首先,我們對TimerTask進行修改,讓它某一次任務(wù)產(chǎn)生大量耗時:

TimerTask task = new TimerTask() {
    private int i = 1;
    @Override
    public void run() {
        System.out.print(i + " " + DateUtil.formatNow() + " 開始執(zhí)行, ");
        if(i == 3) {
            ThreadUtil.sleep(11 * 1000);
        }
        System.out.println(DateUtil.formatNow() + " 結(jié)束");
        i++;
    }
};

該任務(wù)在執(zhí)行第3次時,將會休眠11秒,這將會導(dǎo)致延誤后續(xù)的任務(wù)。

2. 固定速率

示例:

Timer timer = new Timer("timer");
timer.scheduleAtFixedRate(task, 5000, 2000);

設(shè)定任務(wù)延遲5秒后執(zhí)行第1次任務(wù),之后每2秒執(zhí)行一次。

輸出:

啟動于:2022-10-31 15:51:24
1 2022-10-31 15:51:29 開始執(zhí)行, 2022-10-31 15:51:29 結(jié)束
2 2022-10-31 15:51:31 開始執(zhí)行, 2022-10-31 15:51:31 結(jié)束
3 2022-10-31 15:51:33 開始執(zhí)行, 2022-10-31 15:51:44 結(jié)束 *
4 2022-10-31 15:51:44 開始執(zhí)行, 2022-10-31 15:51:44 結(jié)束 *
5 2022-10-31 15:51:44 開始執(zhí)行, 2022-10-31 15:51:44 結(jié)束 *
6 2022-10-31 15:51:44 開始執(zhí)行, 2022-10-31 15:51:44 結(jié)束 *
7 2022-10-31 15:51:44 開始執(zhí)行, 2022-10-31 15:51:44 結(jié)束 *
8 2022-10-31 15:51:44 開始執(zhí)行, 2022-10-31 15:51:44 結(jié)束 *
9 2022-10-31 15:51:45 開始執(zhí)行, 2022-10-31 15:51:45 結(jié)束
10 2022-10-31 15:51:47 開始執(zhí)行, 2022-10-31 15:51:47 結(jié)束
11 2022-10-31 15:51:49 開始執(zhí)行, 2022-10-31 15:51:49 結(jié)束

如果不存在第3次耗時11秒的情況下,正常任務(wù)執(zhí)行時間應(yīng)該為:

啟動于:2022-10-31 15:51:24
1 2022-10-31 15:51:29 開始執(zhí)行, 2022-10-31 15:51:29 結(jié)束
2 2022-10-31 15:51:31 開始執(zhí)行, 2022-10-31 15:51:31 結(jié)束
3 2022-10-31 15:51:33 開始執(zhí)行, 2022-10-31 15:51:33 結(jié)束 *
4 2022-10-31 15:51:35 開始執(zhí)行, 2022-10-31 15:51:35 結(jié)束 *
5 2022-10-31 15:51:37 開始執(zhí)行, 2022-10-31 15:51:37 結(jié)束 *
6 2022-10-31 15:51:39 開始執(zhí)行, 2022-10-31 15:51:39 結(jié)束 *
7 2022-10-31 15:51:41 開始執(zhí)行, 2022-10-31 15:51:41 結(jié)束 *
8 2022-10-31 15:51:43 開始執(zhí)行, 2022-10-31 15:51:43 結(jié)束 *
9 2022-10-31 15:51:45 開始執(zhí)行, 2022-10-31 15:51:45 結(jié)束
10 2022-10-31 15:51:47 開始執(zhí)行, 2022-10-31 15:51:47 結(jié)束
11 2022-10-31 15:51:49 開始執(zhí)行, 2022-10-31 15:51:49 結(jié)束

但是在第3次執(zhí)行任務(wù)時因為執(zhí)行耗時11秒,第4次本該在15:51:35開始執(zhí)行并完成任務(wù),卻到了15:51:44才執(zhí)行完成,這11秒延誤了后續(xù)5個任務(wù)的正常執(zhí)行,因此在15:51:44時,scheduleAtFixedRate趕作業(yè)把延誤的5個任務(wù)一起執(zhí)行了。

最后趕上了原本的進度,第9個任務(wù)準時在15:51:45執(zhí)行。

3. 固定延時

示例:

Timer timer = new Timer("timer");
timer.schedule(task, 5000, 2000);

輸出:

啟動于:2022-10-31 15:56:59
1 2022-10-31 15:57:04 開始執(zhí)行, 2022-10-31 15:57:04 結(jié)束
2 2022-10-31 15:57:06 開始執(zhí)行, 2022-10-31 15:57:06 結(jié)束
3 2022-10-31 15:57:08 開始執(zhí)行, 2022-10-31 15:57:19 結(jié)束 *
4 2022-10-31 15:57:19 開始執(zhí)行, 2022-10-31 15:57:19 結(jié)束
5 2022-10-31 15:57:21 開始執(zhí)行, 2022-10-31 15:57:21 結(jié)束
6 2022-10-31 15:57:24 開始執(zhí)行, 2022-10-31 15:57:24 結(jié)束
7 2022-10-31 15:57:26 開始執(zhí)行, 2022-10-31 15:57:26 結(jié)束
8 2022-10-31 15:57:28 開始執(zhí)行, 2022-10-31 15:57:28 結(jié)束
9 2022-10-31 15:57:30 開始執(zhí)行, 2022-10-31 15:57:30 結(jié)束
10 2022-10-31 15:57:32 開始執(zhí)行, 2022-10-31 15:57:32 結(jié)束

如果不存在第3次耗時11秒的情況下,正常任務(wù)執(zhí)行時間應(yīng)該為:

啟動于:2022-10-31 15:56:59
1 2022-10-31 15:57:04 開始執(zhí)行, 2022-10-31 15:57:04 結(jié)束
2 2022-10-31 15:57:06 開始執(zhí)行, 2022-10-31 15:57:06 結(jié)束
3 2022-10-31 15:57:08 開始執(zhí)行, 2022-10-31 15:57:08 結(jié)束 *
4 2022-10-31 15:57:10 開始執(zhí)行, 2022-10-31 15:57:10 結(jié)束
5 2022-10-31 15:57:12 開始執(zhí)行, 2022-10-31 15:57:12 結(jié)束
6 2022-10-31 15:57:14 開始執(zhí)行, 2022-10-31 15:57:14 結(jié)束
7 2022-10-31 15:57:16 開始執(zhí)行, 2022-10-31 15:57:16 結(jié)束
8 2022-10-31 15:57:18 開始執(zhí)行, 2022-10-31 15:57:18 結(jié)束
9 2022-10-31 15:57:20 開始執(zhí)行, 2022-10-31 15:57:20 結(jié)束
10 2022-10-31 15:57:22 開始執(zhí)行, 2022-10-31 15:57:22 結(jié)束

使用schedule調(diào)度,第4次任務(wù)本該在15:57:10開始執(zhí)行,但由于耗時11秒直到15:57:19才開始。

而第3次任務(wù)實際是在19秒完成,完成后又在19秒立即執(zhí)行第4次,中間少了2秒間隔,第4次完成后接著開始2秒一次,變?yōu)榱藦?1秒開始執(zhí)行第5次。

和我原本的推測不一樣的是,本以為19秒完成后,第4次會隔2秒在21秒執(zhí)行,沒想到19秒會立即執(zhí)行。

猜測與delay參數(shù)有關(guān),但調(diào)整了delay后仍然一樣,完成的那一秒還是會馬上再執(zhí)行第4次任務(wù)。

通過以上測試對比,我們可以感受到Timer中固定速率和固定延時的區(qū)別,但為了避免出錯,使用Timer時應(yīng)讓TimerTask耗時盡可能短。

4. 其他要點

1.以上是僅第3次任務(wù)加上了耗時11秒,如果是所有任務(wù)都耗時11秒呢?

如果每次任務(wù)執(zhí)行都耗時11秒,那么無論是固定速率還是固定延時,都將是11秒執(zhí)行一個任務(wù)。

2.如果改為schedule(TimerTasktask,DatefirstTime,longperiod)和scheduleAtFixedRate(TimerTasktask,DatefirstTime,longperiod)來調(diào)度任務(wù),firstTime指定為10點,而當(dāng)前系統(tǒng)時間為11點,會出現(xiàn)什么情況呢?

雖然firstTime已經(jīng)過期,但是Timer將會立即開始執(zhí)行任務(wù),之后按照period間隔重復(fù)執(zhí)行任務(wù)。

3.如果TimerTask執(zhí)行過程中拋出了異常會發(fā)生什么事情?

Timer內(nèi)部僅維護一個線程,當(dāng)任一TimerTask拋出異常,將導(dǎo)致此線程終止運行,該Timer負責(zé)的所有任務(wù)都無法執(zhí)行。

四、調(diào)度多個TimerTask

在上一節(jié)中,介紹的是一個可重復(fù)執(zhí)行的TimeTask,如果執(zhí)行耗時大于設(shè)定的間隔period,將會影響該TimerTask下一次執(zhí)行的時間點。

而這一節(jié)則是為了單獨說明,一個Timer同時調(diào)度多個TimeTask也會互相影響。

示例:

TimerTask task1 = new TimerTask() {
    private int i = 1;
    @Override
    public void run() {
        System.out.print(i + " task1:" + DateUtil.formatNow() + " 開始執(zhí)行, ");
        ThreadUtil.sleep(11 * 1000);
        System.out.println(DateUtil.formatNow() + " 結(jié)束");
        i++;
    }
};
TimerTask task2 = new TimerTask() {
    private int i = 1;
    @Override
    public void run() {
        System.out.print(i + "  task2:" + DateUtil.formatNow() + " 開始執(zhí)行, ");
        ThreadUtil.sleep(11 * 1000);
        System.out.println(DateUtil.formatNow() + " 結(jié)束");
        i++;
    }
};

Timer timer = new Timer("timer");
timer.scheduleAtFixedRate(task1, 5000, 2000);
timer.scheduleAtFixedRate(task2, 5000, 2000);

輸出:

1 task1:2022-10-31 16:58:27 開始執(zhí)行, 2022-10-31 16:58:38 結(jié)束
1 task2:2022-10-31 16:58:38 開始執(zhí)行, 2022-10-31 16:58:49 結(jié)束
2 task2:2022-10-31 16:58:49 開始執(zhí)行, 2022-10-31 16:59:00 結(jié)束
2 task1:2022-10-31 16:59:00 開始執(zhí)行, 2022-10-31 16:59:11 結(jié)束
3 task1:2022-10-31 16:59:11 開始執(zhí)行, 2022-10-31 16:59:22 結(jié)束
3 task2:2022-10-31 16:59:22 開始執(zhí)行, 2022-10-31 16:59:33 結(jié)束
4 task2:2022-10-31 16:59:33 開始執(zhí)行, 2022-10-31 16:59:44 結(jié)束
4 task1:2022-10-31 16:59:44 開始執(zhí)行, 2022-10-31 16:59:55 結(jié)束

可以發(fā)現(xiàn),task1和task2其實都沒有按照既定時間去執(zhí)行任務(wù)了。

根本原因是在于,Timer內(nèi)部僅維護一個線程執(zhí)行所有TimerTask,為了避免錯誤,一個Timer對象最好僅調(diào)度一個TimerTask對象,除非可以確保多個TimerTask之間一定不會相互影響。

因此編寫TimerTask時應(yīng)當(dāng)自行捕獲異常。

五、取消任務(wù)

Timer在創(chuàng)建時實際上是默認在內(nèi)部維護了一個非守護線程,即使任務(wù)全部執(zhí)行完成,線程也并不會銷毀。

Timer提供cancel()方法,可以手動調(diào)用取消定時器所有的任務(wù),并銷毀定時器。

如果想要Timer內(nèi)部創(chuàng)建的是守護線程,可以使用以下構(gòu)造方法創(chuàng)建定時器,設(shè)置isDaemon為true:

  • Timer(booleanisDaemon)

Timer(Stringname,booleanisDaemon)

如果沒有自己定義name參數(shù),默認Timer內(nèi)部自動命名為“Timer-遞增序號”,作為內(nèi)部線程的線程名稱,在構(gòu)造方法內(nèi)啟動此線程。

如果是要取消單個任務(wù),可以使用TimerTask的cancel()方法。

當(dāng)TimerTask調(diào)用cancel之后,任務(wù)是取消了,但Timer自身并不能馬上知道TimerTask被取消,而是在準備執(zhí)行前才知道,因此Timer內(nèi)部還維護著這個任務(wù)的引用。若希望Timer立即清除引用,可調(diào)用Timer.purge()立即執(zhí)行清除。

到此這篇關(guān)于Java Timer使用講解的文章就介紹到這了,更多相關(guān)Java Timer使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 在java中如何將inputStream對象轉(zhuǎn)換為File對象(不生成本地文件)

    在java中如何將inputStream對象轉(zhuǎn)換為File對象(不生成本地文件)

    這篇文章主要介紹了在java中如何將inputStream對象轉(zhuǎn)換為File對象(不生成本地文件),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Spring?Boot項目獲取resources目錄下文件并返回給前端的方案

    Spring?Boot項目獲取resources目錄下文件并返回給前端的方案

    我們在項目中經(jīng)常碰到需要讀取固定文件的場景,如模板文件,一般做法是將文件放在resources目錄下,程序通過多種方式可以順利讀取文件,這篇文章主要給大家介紹了關(guān)于Spring?Boot項目獲取resources目錄下文件并返回給前端的相關(guān)資料,需要的朋友可以參考下
    2024-07-07
  • SpringBoot3實現(xiàn)國際化的代碼步驟

    SpringBoot3實現(xiàn)國際化的代碼步驟

    國際化,簡稱 i18n,源自國際化英文單詞 internationalization 中首字母 i 與尾字母 n 之間有 18 個字母,本文給大家介紹了SpringBoot3實現(xiàn)國際化的操作步驟,并通過代碼示例講解的非常詳細,需要的朋友可以參考下
    2024-12-12
  • Kotlin與Java 泛型缺陷和應(yīng)用場景詳解

    Kotlin與Java 泛型缺陷和應(yīng)用場景詳解

    這篇文章主要為大家介紹了Kotlin與Java 泛型缺陷和應(yīng)用場景詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • springboot整合log4j的踩坑實戰(zhàn)記錄

    springboot整合log4j的踩坑實戰(zhàn)記錄

    log日志的重要性不言而喻,所以我們需要在系統(tǒng)內(nèi)根據(jù)實際的業(yè)務(wù)進行日志的整合,下面這篇文章主要給大家介紹了關(guān)于springboot整合log4j的踩坑實戰(zhàn)記錄,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-04-04
  • 如何利用Java輸出鏈表中倒數(shù)第k個結(jié)點

    如何利用Java輸出鏈表中倒數(shù)第k個結(jié)點

    這篇文章主要給大家介紹了關(guān)于如何利用Java輸出鏈表中倒數(shù)第k個結(jié)點的相關(guān)資料,文中通過實例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2021-12-12
  • springboot項目開啟https協(xié)議的項目實現(xiàn)

    springboot項目開啟https協(xié)議的項目實現(xiàn)

    本文主要介紹了springboot項目開啟https協(xié)議的項目實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Java窗體動態(tài)加載磁盤文件的實現(xiàn)方法

    Java窗體動態(tài)加載磁盤文件的實現(xiàn)方法

    這篇文章主要介紹了Java窗體動態(tài)加載磁盤文件的實現(xiàn)方法,需要的朋友可以參考下
    2014-03-03
  • 深入淺出講解Java比較器及數(shù)學(xué)常用類

    深入淺出講解Java比較器及數(shù)學(xué)常用類

    這篇文章主要介紹了深入淺出講解Java比較器及數(shù)學(xué)常用類,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • Java?數(shù)據(jù)結(jié)構(gòu)深入理解ArrayList與順序表

    Java?數(shù)據(jù)結(jié)構(gòu)深入理解ArrayList與順序表

    ArrayList?類是一個可以動態(tài)修改的數(shù)組,與普通數(shù)組的區(qū)別就是它是沒有固定大小的限制,我們可以添加或刪除元素。ArrayList?繼承了?AbstractList?,并實現(xiàn)了?List?接口,順序表是將元素順序地存放在一塊連續(xù)的存儲區(qū)里,元素間的順序關(guān)系由它們的存儲順序自然表示
    2022-04-04

最新評論

金沙县| 时尚| 滦南县| 博白县| 长治县| 溧水县| 金华市| 姜堰市| 山东省| 越西县| 宁蒗| 平乡县| 新乐市| 大港区| 桃园市| 广汉市| 濮阳市| 弥渡县| 远安县| 沐川县| 高邮市| 营口市| 年辖:市辖区| 玉环县| 和田市| 巩留县| 商丘市| 资溪县| 台中市| 潜江市| 宁远县| 昌平区| 常德市| 高雄县| 焦作市| 永寿县| 蒲江县| 伊春市| 应城市| 大丰市| 北流市|