欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

1. 概要

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

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

2. 簡述

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

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

2.1 固定速率

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

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

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

2.2 固定延時(shí)

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

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

2.3 區(qū)別

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

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

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

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

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

3. Timer 的用法

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

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

這個(gè) API 的意思是:延時(shí) delay 后開始按照 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 解釋

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

有了上面的基礎(chǔ)再來看輸出,這就是為什么任務(wù)執(zhí)行了 3s 最終還是在 49s 就開始執(zhí)行下一個(gè)任務(wù),因?yàn)?44s 執(zhí)行任務(wù)的時(shí)候會根據(jù)當(dāng)前執(zhí)行時(shí)間算出下一個(gè)任務(wù)執(zhí)行時(shí)間應(yīng)該是 44 + 5 = 49s,而第二個(gè)任務(wù) 49s 執(zhí)行的時(shí)候會算出下一個(gè)任務(wù)執(zhí)行時(shí)間是 49 + 5 = 54s,但是由于任務(wù)執(zhí)行時(shí)間長達(dá) 8s,導(dǎo)致下一個(gè)任務(wù)根本沒時(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ù),以此類推

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

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

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

顧名思義,就是設(shè)置一個(gè)第一次啟動的時(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 開始,接著每次執(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 開始執(zhí)行第一次,然后往隊(duì)列立馬加入一個(gè) 32s 的下一次執(zhí)行的任務(wù),當(dāng)前任務(wù)執(zhí)行時(shí)間 3s

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

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

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

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

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

和上面一樣就是選擇某個(gè)首次執(zhí)行時(shí)間點(diǎn)開始執(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ù),來看例子:

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í)間之后開始執(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用法的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java實(shí)現(xiàn)一個(gè)簡單的緩存方法

    Java實(shí)現(xiàn)一個(gè)簡單的緩存方法

    本篇文章主要介紹了Java實(shí)現(xiàn)一個(gè)簡單的緩存方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-04-04
  • rabbitmq五種模式詳解(含實(shí)現(xiàn)代碼)

    rabbitmq五種模式詳解(含實(shí)現(xiàn)代碼)

    這篇文章主要介紹了rabbitmq五種模式詳解(含實(shí)現(xiàn)代碼),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • Java反射機(jī)制用法總結(jié)

    Java反射機(jī)制用法總結(jié)

    反射機(jī)制是在運(yùn)行狀態(tài)中,對于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對于任意一個(gè)對象,都能夠調(diào)用它的任意一個(gè)方法和屬性;這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為java語言的反射機(jī)制。下面我們來一起學(xué)習(xí)一下吧
    2019-05-05
  • java實(shí)現(xiàn)mongodb的數(shù)據(jù)庫連接池

    java實(shí)現(xiàn)mongodb的數(shù)據(jù)庫連接池

    這篇文章主要介紹了基于java實(shí)現(xiàn)mongodb的數(shù)據(jù)庫連接池,Java通過使用mongo-2.7.3.jar包實(shí)現(xiàn)mongodb連接池,感興趣的小伙伴們可以參考一下
    2015-12-12
  • 淺談java中String與StringBuffer的不同

    淺談java中String與StringBuffer的不同

    String在棧中,StringBuffer在堆中!所以String是不可變的,數(shù)據(jù)是共享的。StringBuffer都是獨(dú)占的,是可變的(因?yàn)槊看味际莿?chuàng)建新的對象?。?/div> 2015-11-11
  • Java多線程——之一創(chuàng)建線程的四種方法

    Java多線程——之一創(chuàng)建線程的四種方法

    這篇文章主要介紹了Java創(chuàng)建線程方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Java跳出多重嵌套循環(huán)代碼實(shí)例

    Java跳出多重嵌套循環(huán)代碼實(shí)例

    這篇文章主要介紹了Java跳出多重嵌套循環(huán),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Java生成遞增流水號(編號+時(shí)間+流水號)簡單示例

    Java生成遞增流水號(編號+時(shí)間+流水號)簡單示例

    這篇文章主要給大家介紹了關(guān)于Java生成遞增流水號(編號+時(shí)間+流水號)的相關(guān)資料,在開發(fā)項(xiàng)目漫長的過程中常常會遇到流水號需要自動生成的問題存在,文中給出了詳細(xì)的代碼示例,需要的朋友可以參考下
    2023-07-07
  • Java 時(shí)間格式轉(zhuǎn)換之impleDateFormat與Data API解析與使用

    Java 時(shí)間格式轉(zhuǎn)換之impleDateFormat與Data API解析與使用

    想必大家對 SimpleDateFormat 并不陌生。SimpleDateFormat 是 Java 中一個(gè)非常常用的類,他是以區(qū)域敏感的方式格式化和解析日期的具體類。 它允許格式化 (date -> text)、語法分析 (text -> date)和標(biāo)準(zhǔn)化
    2021-11-11
  • Java函數(shù)式編程(十):收集器

    Java函數(shù)式編程(十):收集器

    這篇文章主要介紹了Java函數(shù)式編程(十):收集器,本文是系列文章的第10篇,其它文章請參閱本文底部的相關(guān)文章,需要的朋友可以參考下
    2014-09-09

最新評論