" />

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

Java任務(wù)定時執(zhí)行器案例的實現(xiàn)

 更新時間:2022年06月06日 14:36:32   作者:未見花聞  
定時器會執(zhí)行指定的任務(wù),本文主要介紹了Java任務(wù)定時執(zhí)行器案例的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧

??前面的話??

本篇文章將介紹Java多線程案例,定時器,定時器就像鬧鐘一樣,等到了指定的時間,鬧鐘就會發(fā)出響聲來提醒您,而定時器會執(zhí)行指定的任務(wù)。

??1.定時器概述

??1.1認識定時器

java中的定時器,也可以叫做任務(wù)定時執(zhí)行器,顧名思義,就是等到了指定的時間,就去做指定的事情,就像你每周六或周日都要去力扣參加周賽一樣。

所以你如果想要使用定時器,你需要交代時間和對應(yīng)的任務(wù)才行,java標準也提供了帶有定時器功能的類Timer

??1.2Timer類的使用

在java1.8中,Timer給出了四個構(gòu)造方法,這些構(gòu)造方法可以去指定線程的名字和是否將定時器內(nèi)部的線程指定為守護線程。

好了,又出現(xiàn)了一個新概念,這個守護線程是什么鬼?
其實在java中有兩種線程,一種是用戶線程,另外一種是守護線程。用戶線程就是普通的線程,守護線程顧名思義就是守護用戶線程的線程,可以說就是用戶線程的保姆,守護線程與JVM“共存亡”, 只要存在一個用戶線程,程序中所有的守護線程都不會停止工作,直到最后一個用戶線程執(zhí)行完畢,守護線程才會停止工作。守護線程最典型的應(yīng)用就是 GC (垃圾回收器),它就是一個非常稱職的守護者。

??構(gòu)造方法:

序號構(gòu)造方法說明
1public Timer()無參數(shù)構(gòu)造方法,默認定時器關(guān)聯(lián)的線程不是守護線程,線程名字也是默認值
2public Timer(boolean isDaemon)指定定時器中關(guān)聯(lián)的線程是否為守護線程,如果是,參數(shù)為true
3public Timer(String name)指定定時器關(guān)聯(lián)線程名稱,線程類型默認為非守護線程
4public Timer(String name, boolean isDaemon)指定定時器關(guān)聯(lián)線程名和線程類型

Timer類構(gòu)造時內(nèi)部也會創(chuàng)建線程,如果不指定,定時器對象內(nèi)部的線程(為了簡化,就稱為關(guān)聯(lián)線程吧)的類型是用戶線程,而不是守護線程。

??核心方法:

序號方法說明
1public void schedule(TimerTask task, long delay)指定任務(wù),延遲多久執(zhí)行該任務(wù)
2public void schedule(TimerTask task, Date time)指定任務(wù),指定任務(wù)的執(zhí)行時間
3public void schedule(TimerTask task, long delay, long period)連續(xù)執(zhí)行指定任務(wù),延遲時間,連續(xù)執(zhí)行任務(wù)的時間間隔,毫秒為單位
4public void schedule(TimerTask task, Date firstTime, long period)連續(xù)執(zhí)行指定任務(wù),第一次任務(wù)的執(zhí)行時間,連續(xù)執(zhí)行任務(wù)的時間間隔
5public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)與方法4作用相同
6public void scheduleAtFixedRate(TimerTask task, long delay, long period)與方法3作用相同
7public void cancel()終止定時器所有任務(wù),終止執(zhí)行的任務(wù)不受影響

??使用演示:

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.PriorityBlockingQueue;

public class TimeProgram {
    public static void main(String[] args) throws InterruptedException {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("執(zhí)行延后2s執(zhí)行的任務(wù)!");
            }
        }, 2000);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("執(zhí)行延后5s執(zhí)行的任務(wù)!");
            }
        }, 5000);

        //每秒輸出一個mian
        for (int i = 0; i < 5; i++) {
            System.out.println("main");
            Thread.sleep(1000);
        }
    }
}

??運行結(jié)果:

TimerTask類就是專門描述定時器任務(wù)的一個抽象類,它實現(xiàn)了Runnable接口。

public abstract class TimerTask implements Runnable    //jdk源碼

下面我們簡單實現(xiàn)一下定時器,我們就不用TimerTask了,我們直接使用Runnable,因為TimerTask實現(xiàn)了Runnable接口,所以后面測試我們自己所寫的schedule方法時,也可以傳入TimerTask類型的引用,既然是簡單地實現(xiàn),那就不實現(xiàn)連續(xù)執(zhí)行的功能了。

??2.定時器的簡單實現(xiàn)

首先,我們需要建造一個類,來描述定時器的任務(wù),可以使用Runnable加上一個任務(wù)執(zhí)行的時間戳就可以了。
??具體清單:
一個構(gòu)造方法,用來指定任務(wù)和延遲執(zhí)行時間。
兩個獲取方法,用來給外部對象獲取該對象的任務(wù)和執(zhí)行時間。
實現(xiàn)比較器,用于定時器任務(wù)對象的組織,畢竟,每次需要執(zhí)行時間最早的任務(wù),需要用到基于小根堆實現(xiàn)的優(yōu)先隊列,不,還需要考慮多線程的情況,還是使用優(yōu)先級阻塞隊列吧。

//我的任務(wù)
class MyTask implements Comparable<MyTask> {
    //接收具體任務(wù)
    private Runnable runnable;
    //執(zhí)行時的時間戳
    private long time;

    //構(gòu)造方法
    public MyTask(Runnable runnable, int delay) {
        this.runnable = runnable;
        this.time = System.currentTimeMillis() + delay;
    }

    //執(zhí)行任務(wù)
    public void run() {
        this.runnable.run();
    }
    //獲取執(zhí)行時間
    public long getTime() {
        return this.time;
    }

    //實現(xiàn)comparable接口,方便創(chuàng)建優(yōu)先級阻塞隊列
    @Override
    public int compareTo(MyTask o) {
        return (int) (this.time - o.time);
    }
}

接下來就要實現(xiàn)定時器類了,首先我們需要一個數(shù)據(jù)結(jié)構(gòu)來組織定時器任務(wù),并且每次都能將時間最早的任務(wù)找到并執(zhí)行,那么這個數(shù)據(jù)結(jié)構(gòu)非小根堆莫屬了,也就是優(yōu)先級隊列,注意對自定義類使用優(yōu)先級隊列時,一定要實現(xiàn)比較器。

    //每次執(zhí)行任務(wù)時,需要優(yōu)先執(zhí)行時間在前的任務(wù),即每次執(zhí)行任務(wù)要選擇時間戳最小的任務(wù),在多線程情況中優(yōu)先級阻塞隊列是最佳選擇
    private static final PriorityBlockingQueue<MyTask> priorityBlockingQueue = new PriorityBlockingQueue<>();

然后,需要一個方法將任務(wù)安排在優(yōu)先級阻塞隊列中,最后在構(gòu)造定時器對象的時候從優(yōu)先級阻塞隊列中取任務(wù)并在指定的時間執(zhí)行。

按照上圖的邏輯,我們自己實現(xiàn)的定時器類需要有一個線程專門去執(zhí)行任務(wù),執(zhí)行任務(wù)過程中可能會遇到執(zhí)行時間還沒有到的情況,那么線程必須得等待,線程等待的方法有兩種,一種是wait另一種是sleep,這個案例我們推薦前者,因為sleep方法不能中途喚醒,這個案例是有可能需要中途喚醒的,那就是有新任務(wù)插入時,需要重新去優(yōu)先級阻塞隊列拿任務(wù)重復(fù)上述操作,這個喚醒操作可以使用notify方法實現(xiàn),所以需要用到wait/notify組合拳,既然需要使用wait/notify那么就得有鎖,所以我們可以使用一個專門的鎖對象來加鎖。

??實現(xiàn)代碼:

//我的定時類 用來管理任務(wù)
class MyTimer {
    //專門對鎖對象
    private final Object locker = new Object();
    //每次執(zhí)行任務(wù)時,需要優(yōu)先執(zhí)行時間在前的任務(wù),即每次執(zhí)行任務(wù)要選擇時間戳最小的任務(wù),在多線程情況中優(yōu)先級阻塞隊列是最佳選擇
    private static final PriorityBlockingQueue<MyTask> priorityBlockingQueue = new PriorityBlockingQueue<>();

    //安排任務(wù)
    public void schedule(Runnable runnable, int delay) {
        //將任務(wù)放入小根堆中
        MyTask task = new MyTask(runnable, delay);
        priorityBlockingQueue.put(task);
        //每次當新任務(wù)加載到阻塞隊列時,需要中途喚醒線程,因為新進來的任務(wù)可能是最早需要執(zhí)行的
        synchronized (locker) {
            locker.notify();
        }
    }
    public MyTimer() {
        Thread thread = new Thread(() -> {
            while (true) {
                try {
                    //加載任務(wù),確定執(zhí)行時機
                    MyTask myTask = priorityBlockingQueue.take();
                    long curTime = System.currentTimeMillis();
                    //時間未到,將任務(wù)放回
                    if (curTime < myTask.getTime()) {
                        synchronized (locker) {
                            priorityBlockingQueue.put(myTask);
                            //放回任務(wù)后,不能立即就再次取該任務(wù)加載,需要設(shè)置一個再次加載的等待時間,建議使用wait帶參數(shù)的方法
                            //因為wait方法可以使用notify進行中途喚醒,而sleep不能中途喚醒
                            int delay = (int)(myTask.getTime() - curTime);
                            locker.wait(delay);
                        }
                    } else {
                        System.out.println(Thread.currentThread().getName() + "線程收到任務(wù),正在執(zhí)行中!");
                        myTask.run();
                        System.out.println(Thread.currentThread().getName() + "線程執(zhí)行任務(wù)完畢,正在等待新任務(wù)!");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        //不要忘了啟動線程
        thread.start();
    }
}

??上面是我們實現(xiàn)定時器的代碼,我們來測試一下:

import java.util.TimerTask;
import java.util.concurrent.PriorityBlockingQueue;

public class TimeProgram {
    public static void main(String[] args) throws InterruptedException {
        MyTimer timer = new MyTimer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("執(zhí)行延后2s執(zhí)行的任務(wù)!");
            }
        }, 2000);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("執(zhí)行延后5s執(zhí)行的任務(wù)!");
            }
        }, 5000);

        //每秒輸出一個mian
        for (int i = 0; i < 5; i++) {
            System.out.println("main");
            Thread.sleep(1000);
        }
    }
}

??執(zhí)行結(jié)果:

好了,任務(wù)定時執(zhí)行器你學(xué)會了嗎?

到此這篇關(guān)于Java任務(wù)定時執(zhí)行器案例的實現(xiàn)的文章就介紹到這了,更多相關(guān)Java任務(wù)定時執(zhí)行器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java 求解二維數(shù)組列最小值

    java 求解二維數(shù)組列最小值

    這篇文章主要介紹了java 求解二維數(shù)組列最小值的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • Java中的5種同步輔助類介紹

    Java中的5種同步輔助類介紹

    你提交了一些任務(wù),但你想等它們都完成了再做另外一些事情;你提交了一些任務(wù),但是不想讓它們立刻執(zhí)行,等你喊123開始的時候,它們才開始執(zhí)行;等等這些場景,線程之間需要相互配合,或者等待某一個條件成熟執(zhí)行。這些場景想你就需要用到同步輔助類
    2014-04-04
  • 關(guān)于Spring?Ioc和DI注解的問題

    關(guān)于Spring?Ioc和DI注解的問題

    這篇文章主要介紹了Spring?Ioc和DI注解,本文給大家介紹的非常詳細,對大家的學(xué)習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • MyBatis 中 ${}和 #{}的正確使用方法(千萬不要亂用)

    MyBatis 中 ${}和 #{}的正確使用方法(千萬不要亂用)

    這篇文章主要介紹了MyBatis 中 ${}和 #{}的正確使用方法,本文給大家提到了MyBatis 中 ${}和 #{}的區(qū)別,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • 利用java實現(xiàn)二叉搜索樹

    利用java實現(xiàn)二叉搜索樹

    這篇文章主要介紹了利用java實現(xiàn)二叉搜索樹,文中有非常詳細的代碼示例,對正在學(xué)習java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • 詳解Java冒泡排序

    詳解Java冒泡排序

    本篇文章通過代碼實例給大家詳細分析了Java冒泡排序的原理,有興趣的朋友可以學(xué)習下。
    2018-02-02
  • 多模塊maven的deploy集成gitlab?ci自動發(fā)版配置

    多模塊maven的deploy集成gitlab?ci自動發(fā)版配置

    這篇文章主要為大家介紹了多模塊maven項目deploy集成gitlab?ci自動發(fā)版的配置流程步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-02-02
  • Java壓縮解壓縮工具類

    Java壓縮解壓縮工具類

    這篇文章主要為大家詳細介紹了Java壓縮解壓縮工具類,如何壓縮單個文件,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • JAVA多線程和并發(fā)基礎(chǔ)面試問答(翻譯)

    JAVA多線程和并發(fā)基礎(chǔ)面試問答(翻譯)

    多線程和并發(fā)問題是Java技術(shù)面試中面試官比較喜歡問的問題之一。在這里,從面試的角度列出了大部分重要的問題,但是你仍然應(yīng)該牢固的掌握Java多線程基礎(chǔ)知識來對應(yīng)日后碰到的問題
    2014-09-09
  • 淺談三分鐘學(xué)習Java泛型中T、E、K、V、?的含義

    淺談三分鐘學(xué)習Java泛型中T、E、K、V、?的含義

    這篇文章主要介紹了淺談三分鐘學(xué)習Java泛型中T、E、K、V、?的含義,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧
    2019-12-12

最新評論

垣曲县| 洛隆县| 万山特区| 通城县| 岑溪市| 桓台县| 利辛县| 寿阳县| 枣庄市| 闸北区| 南江县| 彩票| 望奎县| 延津县| 广汉市| 临江市| 南宁市| 岑溪市| 鹿邑县| 隆昌县| 澄江县| 安岳县| 汉阴县| 永定县| 平顺县| 铜陵市| 修文县| 佳木斯市| 乐东| 邛崃市| 博野县| 凭祥市| 科尔| 青海省| 商丘市| 永济市| 高密市| 连云港市| 色达县| 东丽区| 无棣县|