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

Java定時(shí)/延時(shí)任務(wù)之Timer用法詳解

 更新時(shí)間:2024年12月15日 10:37:12   作者:JWASX  
在?Java?Development?Kit?(JDK)?中,java.util.Timer?是一個(gè)用于調(diào)度任務(wù)的工具類(lèi),本文主要來(lái)和大家聊聊Timer的用法,有需要的小伙伴可以了解下

1. 概要

上一篇文章地址:定時(shí)/延時(shí)任務(wù)-自己實(shí)現(xiàn)一個(gè)簡(jiǎn)單的定時(shí)器

在上一篇文章中,我們自己實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的 Timer 并提出了一些缺點(diǎn),下面我們就來(lái)看看 JDK 中的 Timer 用法

2. 簡(jiǎn)述

在 Java Development Kit (JDK) 中,java.util.Timer 是一個(gè)用于調(diào)度任務(wù)的工具類(lèi)。Timer 類(lèi)使用一個(gè)后臺(tái)線(xiàn)程來(lái)遍歷隊(duì)列中的任務(wù),同時(shí)可以按照固定的延時(shí)或者固定的速率來(lái)重復(fù)執(zhí)行。

首先在介紹 Timer 的 API 之前,先來(lái)看兩個(gè)概念:

2.1 固定速率

固定速率 策略表示任務(wù)在固定的時(shí)間間隔內(nèi)重復(fù)執(zhí)行,不管任務(wù)的執(zhí)行時(shí)間有多長(zhǎng),如果任務(wù)的執(zhí)行時(shí)間超過(guò)了時(shí)間間隔,那么下一個(gè)任務(wù)會(huì)在當(dāng)前任務(wù)執(zhí)行完畢之后就會(huì)馬上開(kāi)始執(zhí)行,下面是一個(gè)例子:假設(shè)我們?cè)O(shè)置了一個(gè)固定速率為 5 的任務(wù),從 0s 開(kāi)始執(zhí)行,也就是說(shuō)這個(gè)任務(wù) 5s 執(zhí)行一次:

  • 第一次執(zhí)行: 在 0s 開(kāi)始執(zhí)行一次,假設(shè)執(zhí)行時(shí)間是 3s
  • 第二次執(zhí)行: 在 5s 開(kāi)始執(zhí)行第二次,假設(shè)執(zhí)行的時(shí)候被阻塞了,執(zhí)行了 8s
  • 第三次執(zhí)行: 在 13s 開(kāi)始執(zhí)行第三次,假設(shè)執(zhí)行的時(shí)候被阻塞了,執(zhí)行了 3s
  • 第四次執(zhí)行: 在 16s 開(kāi)始執(zhí)行第四次,假設(shè)執(zhí)行的時(shí)候沒(méi)有被阻塞
  • 第四次執(zhí)行: 在 20s 開(kāi)始執(zhí)行第五次,假設(shè)執(zhí)行的時(shí)候沒(méi)有被阻塞

看了上面的過(guò)程分析,你可能有點(diǎn)懵,沒(méi)關(guān)系,等到下面的時(shí)候會(huì)有例子并解釋

2.2 固定延時(shí)

固定延時(shí) 策略表示任務(wù)在當(dāng)前任務(wù)執(zhí)行完成之后,固定延時(shí)一段時(shí)間再執(zhí)行下一個(gè)任務(wù),下面是一個(gè)例子:假設(shè)我們?cè)O(shè)置了一個(gè)固定速率為 5 的任務(wù),從 0s 開(kāi)始執(zhí)行,也就是說(shuō)這個(gè)任務(wù) 5s 執(zhí)行一次:

  • 第一次執(zhí)行: 在 0s 開(kāi)始執(zhí)行一次,假設(shè)執(zhí)行時(shí)間是 3s
  • 第二次執(zhí)行: 在 5s 開(kāi)始執(zhí)行第二次,假設(shè)執(zhí)行的時(shí)候被阻塞了,執(zhí)行了 8s
  • 第三次執(zhí)行: 在 13s 開(kāi)始執(zhí)行第三次,假設(shè)執(zhí)行的時(shí)候被阻塞了,執(zhí)行了 3s
  • 第四次執(zhí)行: 在 18s 開(kāi)始執(zhí)行第四次,假設(shè)執(zhí)行的時(shí)候沒(méi)有被阻塞
  • 第四次執(zhí)行: 在 23s 開(kāi)始執(zhí)行第五次,假設(shè)執(zhí)行的時(shí)候沒(méi)有被阻塞

2.3 區(qū)別

看了上面兩種方式的分析,可以做一個(gè)小的總結(jié):

固定速率: 任務(wù)會(huì)按照固定時(shí)間間隔執(zhí)行,如果任務(wù)執(zhí)行的時(shí)間大于時(shí)間間隔,那么下一個(gè)任務(wù)會(huì)馬上執(zhí)行

固定延時(shí): 任務(wù)會(huì)按照固定延時(shí)執(zhí)行,如果任務(wù)執(zhí)行的時(shí)間小于時(shí)間間隔,那么兩次任務(wù)的執(zhí)行時(shí)間間隔就是設(shè)置的延時(shí);如果任務(wù)執(zhí)行的時(shí)間大于時(shí)間間隔,那么兩次任務(wù)執(zhí)行的時(shí)間間隔就是任務(wù)執(zhí)行的時(shí)間,也就是說(shuō)下一次任務(wù)會(huì)馬上執(zhí)行

固定速率 這種方式比適合用于嚴(yán)格要求按照時(shí)間間隔執(zhí)行的任務(wù),比如心跳探測(cè)、數(shù)據(jù)收集等…

固定延時(shí) 執(zhí)行任務(wù)的時(shí)間不固定,但是得確保每一次任務(wù)執(zhí)行完之后有一定時(shí)間間隔再執(zhí)行下一次的任務(wù),比如日志收集、數(shù)據(jù)清理等…

3. Timer 的用法

下面我們就來(lái)介紹下 Timer 的幾個(gè) API 的用法

3.1 固定延時(shí) - public void schedule(TimerTask task, long delay, long period)

這個(gè) API 的意思是:延時(shí) delay 后開(kāi)始按照 period 的間隔執(zhí)行

public class Pra {

    public static void main(String[] args) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    System.out.println("Thread-Current: " + Thread.currentThread().getName() + ", time = " + getTime());
                    if(Math.random() < 0.5){
                        System.out.println("sleep: 3s");
                        Thread.sleep(3000);
                    } else {
                        System.out.println("sleep: 8s");
                        Thread.sleep(8000);
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, 0, 5000);
    }

    private static String getTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        return sdf.format(new Date());
    }

}

輸出結(jié)果如下:

3.1.1 解釋

解釋?zhuān)篢imer 源碼中對(duì)于任務(wù)的添加是線(xiàn)程被喚醒后獲取到任務(wù),之后就會(huì)立馬計(jì)算出下一次該任務(wù)的調(diào)度時(shí)間加入隊(duì)列中

有了上面的基礎(chǔ)再來(lái)看輸出,這就是為什么任務(wù)執(zhí)行了 3s 最終還是在 49s 就開(kāi)始執(zhí)行下一個(gè)任務(wù),因?yàn)?44s 執(zhí)行任務(wù)的時(shí)候會(huì)根據(jù)當(dāng)前執(zhí)行時(shí)間算出下一個(gè)任務(wù)執(zhí)行時(shí)間應(yīng)該是 44 + 5 = 49s,而第二個(gè)任務(wù) 49s 執(zhí)行的時(shí)候會(huì)算出下一個(gè)任務(wù)執(zhí)行時(shí)間是 49 + 5 = 54s,但是由于任務(wù)執(zhí)行時(shí)間長(zhǎng)達(dá) 8s,導(dǎo)致下一個(gè)任務(wù)根本沒(méi)時(shí)間被調(diào)度,所以只能在 57s 執(zhí)行完之后去看隊(duì)列,發(fā)現(xiàn)隊(duì)列里面 54s 的任務(wù)早就到時(shí)間了,這時(shí)候算出下一個(gè)任務(wù)的執(zhí)行時(shí)間是 57 + 5 = 02s,于是把這個(gè)任務(wù)加入到隊(duì)列中,然后立馬調(diào)度這個(gè) 54s 的任務(wù),以此類(lèi)推

你可能會(huì)有疑問(wèn):如果我任務(wù)執(zhí)行時(shí)間是 8s,任務(wù)間隔是 3s,不會(huì)導(dǎo)致執(zhí)行完一個(gè)任務(wù)之后隊(duì)列中會(huì)有多個(gè)沒(méi)有執(zhí)行的任務(wù)嗎?并不會(huì),因?yàn)楣潭ㄑ訒r(shí)是按照當(dāng)前時(shí)間來(lái)算下一個(gè)任務(wù)的計(jì)算時(shí)間,所以任務(wù)執(zhí)行時(shí)間大于任務(wù)間隔時(shí)間的前提下,不管你間隔多少,都是以任務(wù)執(zhí)行時(shí)間為主

但是對(duì)于固定速率又不一樣了,這個(gè)我們下面會(huì)說(shuō)

3.2 固定延時(shí) - public void schedule(TimerTask task, Date firstTime, long period)

顧名思義,就是設(shè)置一個(gè)第一次啟動(dòng)的時(shí)間點(diǎn),然后以 period 的延時(shí)執(zhí)行,看下面的例子:

public class Pra {

    public static void main(String[] args) {
        Timer timer = new Timer();
        System.out.println("start time = " + getTime());
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    System.out.println("Thread-Current: " + Thread.currentThread().getName() + ", time = " + getTime());
                    if(Math.random() < 0.5){
                        System.out.println("sleep: 3s");
                        Thread.sleep(3000);
                    } else {
                        System.out.println("sleep: 8s");
                        Thread.sleep(8000);
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, new Date(System.currentTimeMillis() + 10000), 5000);
    }

    private static String getTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        return sdf.format(new Date());
    }

}

上面 3.1 已經(jīng)有解釋了

3.3 固定速率 - public void scheduleAtFixedRate(TimerTask task, long delay, long period)

當(dāng)前延時(shí) delay 開(kāi)始,接著每次執(zhí)行的間隔是 period

public class Pra {

    public static void main(String[] args) {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try {
                    System.out.println("Thread-Current: " + Thread.currentThread().getName() + ", time = " + getTime());
                    if(Math.random() < 0.5){
                        System.out.println("sleep: 3s");
                        Thread.sleep(3000);
                    } else {
                        System.out.println("sleep: 8s");
                        Thread.sleep(8000);
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, 0, 5000);
    }

    private static String getTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        return sdf.format(new Date());
    }

}

3.3.1 解釋

1.首先在 27s 開(kāi)始執(zhí)行第一次,然后往隊(duì)列立馬加入一個(gè) 32s 的下一次執(zhí)行的任務(wù),當(dāng)前任務(wù)執(zhí)行時(shí)間 3s

2. 第二次在 32s 開(kāi)始執(zhí)行第而次,然后往隊(duì)列立馬加入一個(gè) 37s 的下一次執(zhí)行的任務(wù),當(dāng)前任務(wù)執(zhí)行時(shí)間 8s

3. 第三次執(zhí)行,當(dāng) 工作線(xiàn)程 執(zhí)行上一個(gè)任務(wù)之后已經(jīng)到 40s 了,由于 40s 已經(jīng)超過(guò)了 37s 的延時(shí)任務(wù)執(zhí)行時(shí)間,于是會(huì)立馬開(kāi)始執(zhí)行,這時(shí)候往隊(duì)列里面添加一個(gè) 42s 執(zhí)行的任務(wù)(下一次執(zhí)行)

4. 第四次執(zhí)行,當(dāng)前任務(wù)執(zhí)行時(shí)間 3s,執(zhí)行完已經(jīng) 43s 了,這時(shí)候執(zhí)行結(jié)束會(huì)發(fā)現(xiàn)隊(duì)列里面的 42s 的任務(wù)已經(jīng)過(guò)期了,就會(huì)往隊(duì)列立馬添加一個(gè) 47s 的任務(wù)(下一次執(zhí)行),然后立馬開(kāi)始執(zhí)行,所以第四次執(zhí)行時(shí)間是 43s

5. 第四次執(zhí)行的時(shí)間是 3s ,執(zhí)行完任務(wù)是 46s,這時(shí)候沒(méi)到 47s,所以沒(méi)有到下一次任務(wù)的執(zhí)行時(shí)間,繼續(xù)等待到 47s 執(zhí)行 第五次任務(wù)

3.4 固定速率 - public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)

和上面一樣就是選擇某個(gè)首次執(zhí)行時(shí)間點(diǎn)開(kāi)始執(zhí)行,后續(xù)速率 period

public class Pra {

    public static void main(String[] args) {
        Timer timer = new Timer();
        System.out.println("start time = " + getTime());
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try {
                    System.out.println("Thread-Current: " + Thread.currentThread().getName() + ", time = " + getTime());
                    if(Math.random() < 0.5){
                        System.out.println("sleep: 3s");
                        Thread.sleep(3000);
                    } else {
                        System.out.println("sleep: 8s");
                        Thread.sleep(8000);
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, new Date(), 5000);
    }

    private static String getTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        return sdf.format(new Date());
    }

}

3.5 非周期任務(wù) - public void schedule(TimerTask task, Date time)

上面都是周期任務(wù),下面這兩個(gè)就是非周期任務(wù),顧名思義就是只執(zhí)行一次的任務(wù),來(lái)看例子:

public class Pra {

    public static void main(String[] args) {
        Timer timer = new Timer();
        System.out.println("start time = " + getTime());
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    System.out.println("Thread-Current: " + Thread.currentThread().getName() + ", time = " + getTime());
                    if(Math.random() < 0.5){
                        System.out.println("sleep: 3s");
                        Thread.sleep(3000);
                    } else {
                        System.out.println("sleep: 8s");
                        Thread.sleep(8000);
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, new Date(System.currentTimeMillis() + 10000));
    }

    private static String getTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        return sdf.format(new Date());
    }

}

3.6 非周期任務(wù) - schedule(TimerTask task, long delay)

延遲 delay 時(shí)間之后開(kāi)始執(zhí)行

public class Pra {

    public static void main(String[] args) {
        Timer timer = new Timer();
        System.out.println("start time = " + getTime());
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    System.out.println("Thread-Current: " + Thread.currentThread().getName() + ", time = " + getTime());
                    if(Math.random() < 0.5){
                        System.out.println("sleep: 3s");
                        Thread.sleep(3000);
                    } else {
                        System.out.println("sleep: 8s");
                        Thread.sleep(8000);
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, 10000);
    }

    private static String getTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        return sdf.format(new Date());
    }

}

以上就是Java定時(shí)/延時(shí)任務(wù)之Timer用法詳解的詳細(xì)內(nèi)容,更多關(guān)于Java Timer用法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java實(shí)現(xiàn)基于NIO的多線(xiàn)程Web服務(wù)器實(shí)例

    Java實(shí)現(xiàn)基于NIO的多線(xiàn)程Web服務(wù)器實(shí)例

    在本篇文章里小編給大家整理的是關(guān)于Java實(shí)現(xiàn)基于NIO的多線(xiàn)程Web服務(wù)器實(shí)例內(nèi)容,需要的朋友們可以學(xué)習(xí)下。
    2020-03-03
  • java實(shí)習(xí)--每天打卡十道面試題!

    java實(shí)習(xí)--每天打卡十道面試題!

    臨近秋招,備戰(zhàn)暑期實(shí)習(xí),祝大家每天進(jìn)步億點(diǎn)點(diǎn)!本篇文章準(zhǔn)備了十道java的常用面試題,希望能夠給大家提供幫助,最后祝大家面試成功,進(jìn)入自己心儀的大廠(chǎng)
    2021-07-07
  • Mybatis使用foreach標(biāo)簽實(shí)現(xiàn)批量插入方式

    Mybatis使用foreach標(biāo)簽實(shí)現(xiàn)批量插入方式

    這篇文章主要介紹了Mybatis使用foreach標(biāo)簽實(shí)現(xiàn)批量插入方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Java 調(diào)整格式日志輸出

    Java 調(diào)整格式日志輸出

    本文主要介紹Java 的日志輸出格式,在開(kāi)發(fā)java的時(shí)候會(huì)經(jīng)??慈罩具M(jìn)行調(diào)試或者查看錯(cuò)誤,這里給大家介紹日志輸出調(diào)整格式,以便大家看日志的時(shí)候更加方便,
    2016-07-07
  • Java實(shí)現(xiàn)折半插入排序算法的示例代碼

    Java實(shí)現(xiàn)折半插入排序算法的示例代碼

    折半插入排序(Binary Insertion Sort)是對(duì)插入排序算法的一種改進(jìn)。不斷的依次將元素插入前面已排好序的序列中。本文將利用Java語(yǔ)言實(shí)現(xiàn)這一排序算法,需要的可以參考一下
    2022-08-08
  • jenkins持續(xù)自動(dòng)化發(fā)布、集成實(shí)踐

    jenkins持續(xù)自動(dòng)化發(fā)布、集成實(shí)踐

    文章描述了在兩臺(tái)服務(wù)器(10.1.1.13和10.1.1.14)上部署Jenkins和Tomcat的過(guò)程,包括環(huán)境準(zhǔn)備、防火墻關(guān)閉、主機(jī)名解析、配置DNS、關(guān)閉SELinux、安裝Java和Tomcat、配置Tomcat用戶(hù)和訪(fǎng)問(wèn)權(quán)限、安裝Jenkins、啟動(dòng)Jenkins服務(wù)以及配置Java項(xiàng)目
    2026-02-02
  • Java靜態(tài)方法不具有多態(tài)性詳解

    Java靜態(tài)方法不具有多態(tài)性詳解

    下面小編就為大家?guī)?lái)一篇Java靜態(tài)方法不具有多態(tài)性詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-06-06
  • 基于SpringBoot+Beetl實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)庫(kù)DDL操作的實(shí)現(xiàn)指南

    基于SpringBoot+Beetl實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)庫(kù)DDL操作的實(shí)現(xiàn)指南

    你是否曾經(jīng)為了應(yīng)對(duì)頻繁的業(yè)務(wù)變化而疲于修改數(shù)據(jù)庫(kù)表結(jié)構(gòu)?是否因?yàn)槭謩?dòng)編寫(xiě)SQL腳本而感到枯燥乏味?本文,我要分享一個(gè)強(qiáng)大的技術(shù)組——SpringBoot?+?Beetl,它可以幫助我們實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)庫(kù)DDL操作,需要的朋友可以參考下
    2026-01-01
  • 出現(xiàn)java.util.ConcurrentModificationException 問(wèn)題及解決辦法

    出現(xiàn)java.util.ConcurrentModificationException 問(wèn)題及解決辦法

    這篇文章主要介紹了出現(xiàn)java.util.ConcurrentModificationException 問(wèn)題及解決辦法的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • Springboot中@Value失效問(wèn)題

    Springboot中@Value失效問(wèn)題

    這篇文章主要介紹了Springboot中@Value失效問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-11-11

最新評(píng)論

宁波市| 乌鲁木齐县| 赫章县| 盐边县| 麻阳| 乐至县| 陆良县| 当阳市| 股票| 古浪县| 陈巴尔虎旗| 竹北市| 辉南县| 北辰区| 扶绥县| 福贡县| 泾川县| 闸北区| 宁夏| 阿图什市| 广灵县| 开平市| 定远县| 宜城市| 焉耆| 仁怀市| 大化| 吉安县| 济阳县| 长泰县| 邵东县| 汉阴县| 柯坪县| 芮城县| 安平县| 双鸭山市| 永川市| 电白县| 辉县市| 日土县| 得荣县|