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

Java多線(xiàn)程案例之定時(shí)器詳解

 更新時(shí)間:2022年10月19日 08:34:30   作者:Moon?Bay  
定時(shí)器也是軟件開(kāi)發(fā)中的一個(gè)重要組件.?類(lèi)似于一個(gè)?“鬧鐘”.?達(dá)到一個(gè)設(shè)定的時(shí)間之后,?就執(zhí)行某個(gè)指定好的代碼。本文就來(lái)和大家詳細(xì)聊聊定時(shí)器的原理與使用,感興趣的可以了解一下

一.什么是定時(shí)器

定時(shí)器也是軟件開(kāi)發(fā)中的一個(gè)重要組件. 類(lèi)似于一個(gè) “鬧鐘”. 達(dá)到一個(gè)設(shè)定的時(shí)間之后, 就執(zhí)行某個(gè)指定好的代碼

定時(shí)器是一種實(shí)際開(kāi)發(fā)中非常常用的組件,我們舉幾個(gè)例子:

1.比如網(wǎng)絡(luò)通信中, 如果對(duì)方 500ms 內(nèi)沒(méi)有返回?cái)?shù)據(jù), 則斷開(kāi)連接嘗試重連

2.比如一個(gè) Map, 希望里面的某個(gè) key 在 3s 之后過(guò)期(自動(dòng)刪除)

以上類(lèi)似于這樣的場(chǎng)景就需要用到定時(shí)器

二.標(biāo)準(zhǔn)庫(kù)中的定時(shí)器(timer)

2.1什么是定時(shí)器

標(biāo)準(zhǔn)庫(kù)中供了一個(gè) Timer 類(lèi). Timer 類(lèi)的核心方法為 schedule ,schedule 包含兩個(gè)參數(shù). 第一個(gè)參數(shù)指定即將要執(zhí)行的任務(wù)代碼TimerTask, 第二個(gè)參數(shù)指定多長(zhǎng)時(shí)間之后執(zhí)行 (單位為毫秒).

Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("hello");
}
}, 3000);

2.2定時(shí)器的使用

Timer的構(gòu)造方法

構(gòu)造方法說(shuō)明
public Timer()無(wú)參數(shù)構(gòu)造方法,默認(rèn)定時(shí)器關(guān)聯(lián)的線(xiàn)程不是守護(hù)線(xiàn)程,線(xiàn)程名字也是默認(rèn)值
public Timer(boolean isDaemon)指定定時(shí)器中關(guān)聯(lián)的線(xiàn)程是否為守護(hù)線(xiàn)程,如果是,參數(shù)為true
public Timer(String name)指定定時(shí)器關(guān)聯(lián)線(xiàn)程名稱(chēng),線(xiàn)程類(lèi)型默認(rèn)為非守護(hù)線(xiàn)程
public Timer(String name, boolean isDaemon)指定定時(shí)器關(guān)聯(lián)線(xiàn)程名和線(xiàn)程類(lèi)型

Timer方法

方法說(shuō)明
public void schedule (TimerTask task, long delay)指定任務(wù),延遲多久執(zhí)行該任務(wù)
public void schedule(TimerTask task, Date time)指定任務(wù),指定任務(wù)的執(zhí)行時(shí)間
public void schedule(TimerTask task, long delay, long period)連續(xù)執(zhí)行指定任務(wù),延遲時(shí)間,連續(xù)執(zhí)行任務(wù)的時(shí)間間隔,毫秒為單位
public void schedule(TimerTask task, Date firstTime, long period)連續(xù)執(zhí)行指定任務(wù),第一次任務(wù)的執(zhí)行時(shí)間,連續(xù)執(zhí)行任務(wù)的時(shí)間間隔
public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)連續(xù)執(zhí)行指定任務(wù),第一次任務(wù)的執(zhí)行時(shí)間,連續(xù)執(zhí)行任務(wù)的時(shí)間間隔
public void scheduleAtFixedRate(TimerTask task, long delay, long period)連續(xù)執(zhí)行指定任務(wù),延遲時(shí)間,連續(xù)執(zhí)行任務(wù)的時(shí)間間隔,毫秒為單位
public void cancel()終止定時(shí)器所有任務(wù),終止執(zhí)行的任務(wù)不受影響

TimerTask是專(zhuān)門(mén)來(lái)實(shí)現(xiàn)Runnable接口的

下面我們會(huì)實(shí)現(xiàn)一下定時(shí)器,我們就不用TimerTask了,我們直接使用Runnable,因?yàn)門(mén)imerTask實(shí)現(xiàn)了Runnable接口,所以后面測(cè)試我們自己所寫(xiě)的schedule方法時(shí),也可以傳入TimerTask類(lèi)型的引用,既然是簡(jiǎn)單地實(shí)現(xiàn),那就不實(shí)現(xiàn)連續(xù)執(zhí)行的功能了。.

public class Test {
    public static void main(String[] args){
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("執(zhí)行線(xiàn)程在5s后執(zhí)行");
            }
        },5000);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("執(zhí)行線(xiàn)程在2s后執(zhí)行");
            }
        },2000);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("執(zhí)行線(xiàn)程在3s后執(zhí)行");
            }
        },3000);
    }
}

三.實(shí)現(xiàn)定時(shí)器

3.1什么是定時(shí)器

定時(shí)器的構(gòu)成:一個(gè)帶優(yōu)先級(jí)的阻塞隊(duì)列

為啥要帶優(yōu)先級(jí)呢?

因?yàn)樽枞?duì)列中的任務(wù)都有各自的執(zhí)行時(shí)刻 (delay). 最先執(zhí)行的任務(wù)一定是 delay 最小的. 使用帶優(yōu)先級(jí)的隊(duì)列就可以高效的把這個(gè) delay 最小的任務(wù)找出來(lái).

1.隊(duì)列中的每個(gè)元素是一個(gè) Task 對(duì)象,Task 中帶有一個(gè)時(shí)間屬性, 隊(duì)首元素就是即將同時(shí)有一個(gè) worker 線(xiàn)程一直掃描隊(duì)首元素, 看隊(duì)首元素是否需要執(zhí)行

class MyTask implements Comparable<MyTask>{
    //執(zhí)行的時(shí)間戳
    private long time;
    //接受具體任務(wù)
    private Runnable runnable;
    //創(chuàng)建MyTask構(gòu)造方法
    public MyTask(Runnable runnable,long time) {
        //通過(guò)currentTimeMillis來(lái)獲取time 中存的是絕對(duì)時(shí)間, 超過(guò)這個(gè)時(shí)間的任務(wù)就應(yīng)該被執(zhí)行
        this.time = System.currentTimeMillis()+time;
        this.runnable = runnable;
    }
    //執(zhí)行任務(wù)
    public void run(){
        this.runnable.run();
    }
    //提供對(duì)外time
    public long getTime() {
        return time;
    }
    //執(zhí)行comparable接口來(lái)進(jìn)行時(shí)間的比較,并將time的long類(lèi)型轉(zhuǎn)換為int類(lèi)型
    @Override
    public int compareTo(MyTask o) {
        return (int)(this.time-o.time);
    }
}

Timer 實(shí)例中, 通過(guò) PriorityBlockingQueue 來(lái)組織若干個(gè) Task 對(duì)象.通過(guò) schedule 來(lái)往隊(duì)列中插入一個(gè)個(gè) Task 對(duì)象.

class MyTimer{
    // 定時(shí)器內(nèi)部要能夠存放多個(gè)任務(wù)
    private PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();
    //為鎖創(chuàng)建一個(gè)對(duì)象
    Object locker = new Object();
    public void schedule(Runnable runnable, long delay) {
        MyTask task = new MyTask(runnable, delay);
        queue.put(task);
        // 每次任務(wù)插入成功之后, 都喚醒一下掃描線(xiàn)程, 讓線(xiàn)程重新檢查一下隊(duì)首的任務(wù)看是否時(shí)間到要執(zhí)行~~
        synchronized (locker) {
            locker.notify();
        }
    }

Timer 類(lèi)中存在一個(gè) worker 線(xiàn)程, 一直不停的掃描隊(duì)首元素, 看看是否能執(zhí)行這個(gè)任務(wù).所謂 “能執(zhí)行” 指的是該任務(wù)設(shè)定的時(shí)間已經(jīng)到達(dá)了

class MyTimer{
    // 定時(shí)器內(nèi)部要能夠存放多個(gè)任務(wù)
    private PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();
    //為鎖創(chuàng)建一個(gè)對(duì)象
    Object locker = new Object();
    public void schedule(Runnable runnable, long delay) {
        MyTask task = new MyTask(runnable, delay);
        queue.put(task);
        // 每次任務(wù)插入成功之后, 都喚醒一下掃描線(xiàn)程, 讓線(xiàn)程重新檢查一下隊(duì)首的任務(wù)看是否時(shí)間到要執(zhí)行~~
        synchronized (locker) {
            locker.notify();
        }
    }
    public MyTimer() {
        Thread t = new Thread(() -> {
            while (true) {
                try {
                    // 先取出隊(duì)首元素
                    MyTask task = queue.take();
                    // 再比較一下看看當(dāng)前這個(gè)任務(wù)時(shí)間到了沒(méi)?
                    long curTime = System.currentTimeMillis();
                    if (curTime < task.getTime()) {
                        // 時(shí)間沒(méi)到, 把任務(wù)再塞回到隊(duì)列中.
                        queue.put(task);
                        // 指定一個(gè)等待時(shí)間,防止有的線(xiàn)程需要等待時(shí)間很長(zhǎng),但是線(xiàn)程一直運(yùn)行等待時(shí)間到來(lái)執(zhí)行,這樣會(huì)占有CPU占有資源
                        synchronized (locker) {
                            locker.wait(task.getTime() - curTime);
                        }
                    } else {
                        // 時(shí)間到了, 執(zhí)行這個(gè)任務(wù)
                        task.run();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
    }
}

3.2最終實(shí)現(xiàn)代碼

package thread;

import java.util.PriorityQueue;
import java.util.concurrent.PriorityBlockingQueue;

// 創(chuàng)建一個(gè)類(lèi), 表示一個(gè)任務(wù).
class MyTask implements Comparable<MyTask> {
    // 任務(wù)具體要干啥
    private Runnable runnable;
    // 任務(wù)具體啥時(shí)候干. 保存任務(wù)要執(zhí)行的毫秒級(jí)時(shí)間戳
    private long time;

    // after 是一個(gè)時(shí)間間隔. 不是絕對(duì)的時(shí)間戳的值
    public MyTask(Runnable runnable, long delay) {
        this.runnable = runnable;
        this.time = System.currentTimeMillis() + delay;
    }

    public void run() {
        runnable.run();
    }

    public long getTime() {
        return time;
    }

    @Override
    public int compareTo(MyTask o) {
        // 到底是誰(shuí)見(jiàn)誰(shuí), 才是一個(gè)時(shí)間小的在前? 需要咱們背下來(lái).
        return (int) (this.time - o.time);
    }
}

class MyTimer {
    // 定時(shí)器內(nèi)部要能夠存放多個(gè)任務(wù)
    private PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();

    public void schedule(Runnable runnable, long delay) {
        MyTask task = new MyTask(runnable, delay);
        queue.put(task);
        // 每次任務(wù)插入成功之后, 都喚醒一下掃描線(xiàn)程, 讓線(xiàn)程重新檢查一下隊(duì)首的任務(wù)看是否時(shí)間到要執(zhí)行~~
        synchronized (locker) {
            locker.notify();
        }
    }

    private Object locker = new Object();

    public MyTimer() {
        Thread t = new Thread(() -> {
            while (true) {
                try {
                    // 先取出隊(duì)首元素
                    MyTask task = queue.take();
                    // 再比較一下看看當(dāng)前這個(gè)任務(wù)時(shí)間到了沒(méi)?
                    long curTime = System.currentTimeMillis();
                    if (curTime < task.getTime()) {
                        // 時(shí)間沒(méi)到, 把任務(wù)再塞回到隊(duì)列中.
                        queue.put(task);
                        // 指定一個(gè)等待時(shí)間
                        synchronized (locker) {
                            locker.wait(task.getTime() - curTime);
                        }
                    } else {
                        // 時(shí)間到了, 執(zhí)行這個(gè)任務(wù)
                        task.run();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
    }
}

public class Test {
    public static void main(String[] args) {
        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello timer!");
            }
        }, 3000);
        System.out.println("main");
    }
}

以上就是Java多線(xiàn)程案例之定時(shí)器詳解的詳細(xì)內(nèi)容,更多關(guān)于Java多線(xiàn)程 定時(shí)器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 關(guān)于BigDecimal類(lèi)型數(shù)據(jù)的絕對(duì)值和相除求百分比

    關(guān)于BigDecimal類(lèi)型數(shù)據(jù)的絕對(duì)值和相除求百分比

    這篇文章主要介紹了關(guān)于BigDecimal類(lèi)型數(shù)據(jù)的絕對(duì)值和相除求百分比,Java在java.math包中提供的API類(lèi)BigDecimal,用來(lái)對(duì)超過(guò)16位有效位的數(shù)進(jìn)行精確的運(yùn)算,需要的朋友可以參考下
    2023-07-07
  • Springboot?對(duì)接支付寶實(shí)現(xiàn)掃碼支付功能

    Springboot?對(duì)接支付寶實(shí)現(xiàn)掃碼支付功能

    本文介紹了如何在Spring?Boot項(xiàng)目中實(shí)現(xiàn)支付寶支付功能,包括沙箱環(huán)境配置、依賴(lài)引入、配置參數(shù)、訂單類(lèi)定義、測(cè)試接口編寫(xiě)等步驟,通過(guò)不同場(chǎng)景下的請(qǐng)求方式(PC端、二維碼、回調(diào)處理、定時(shí)查詢(xún)支付結(jié)果),展示了如何與支付寶API進(jìn)行交互,感興趣的朋友一起看看吧
    2025-03-03
  • java查找文件夾下最新生成的文件的方法

    java查找文件夾下最新生成的文件的方法

    在本篇文章中我們給大家分享了關(guān)于java怎么查找文件夾下最新生成的文件的相關(guān)方法和知識(shí)點(diǎn),有需要的朋友們參考下。
    2019-07-07
  • Java StackTraceElement實(shí)例代碼

    Java StackTraceElement實(shí)例代碼

    這篇文章主要介紹了Java StackTraceElement實(shí)例代碼,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • maven-surefire-plugin總結(jié)示例詳解

    maven-surefire-plugin總結(jié)示例詳解

    這篇文章主要介紹了maven-surefire-plugin總結(jié),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • java郵件發(fā)送簡(jiǎn)單實(shí)現(xiàn)代碼

    java郵件發(fā)送簡(jiǎn)單實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了java郵件發(fā)送簡(jiǎn)單實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Java實(shí)戰(zhàn)練習(xí)之撲克牌魔術(shù)

    Java實(shí)戰(zhàn)練習(xí)之撲克牌魔術(shù)

    這篇文章主要介紹了Java實(shí)戰(zhàn)練習(xí)之撲克牌魔術(shù),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-04-04
  • java實(shí)現(xiàn)清理DNS Cache的方法

    java實(shí)現(xiàn)清理DNS Cache的方法

    這篇文章主要介紹了java實(shí)現(xiàn)清理DNS Cache的方法,分析了幾種常用的清理方法,并給出了反射清理的完整實(shí)例,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-01-01
  • SpringBoot集成分頁(yè)插件PageHelper的配置和使用過(guò)程

    SpringBoot集成分頁(yè)插件PageHelper的配置和使用過(guò)程

    這篇文章主要介紹了SpringBoot集成分頁(yè)插件PageHelper的配置和使用過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 搭建Spring Boot聚合項(xiàng)目的實(shí)現(xiàn)示例

    搭建Spring Boot聚合項(xiàng)目的實(shí)現(xiàn)示例

    本文主要介紹了搭建Spring Boot聚合項(xiàng)目的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04

最新評(píng)論

尉犁县| 安庆市| 新乐市| 门头沟区| 岳西县| 花垣县| 建宁县| 新蔡县| 大荔县| 杨浦区| 县级市| 清镇市| 宁远县| 满洲里市| 广德县| 南陵县| 恭城| 互助| 新化县| 宁河县| 信宜市| 六盘水市| 景洪市| 浏阳市| 阜阳市| 托里县| 衢州市| 千阳县| 丰镇市| 永城市| 体育| 土默特左旗| 原平市| 新余市| 子洲县| 项城市| 荥经县| 丰宁| 东源县| 崇信县| 内乡县|