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

Java定時(shí)器Timer與TimerTask的使用詳解

 更新時(shí)間:2023年10月10日 09:07:25   作者:細(xì)嗅薔薇的大老虎  
這篇文章主要介紹了Java定時(shí)器Timer與TimerTask的使用詳解,在JDK類庫中Timer主要負(fù)責(zé)計(jì)劃任務(wù)的功能,也就是在指定時(shí)間執(zhí)行某一任務(wù),執(zhí)行時(shí)候會(huì)在主線程之外起一個(gè)單獨(dú)的線程執(zhí)行指定的任務(wù),該類主要是設(shè)置任務(wù)計(jì)劃,但封裝的類是TimerTask類,需要的朋友可以參考下

一:簡介

在JDK類庫中Timer主要負(fù)責(zé)計(jì)劃任務(wù)的功能,也就是在指定時(shí)間執(zhí)行某一任務(wù),執(zhí)行時(shí)候會(huì)在主線程之外起一個(gè)單獨(dú)的線程執(zhí)行指定的任務(wù)。該類主要是設(shè)置任務(wù)計(jì)劃,但封裝的類是TimerTask類。 TimerTask是一個(gè)實(shí)現(xiàn)了Runnable接口的抽象類,代表一個(gè)可被執(zhí)行的任務(wù),執(zhí)行任務(wù)的代碼要放在其子類中(TimerTask是抽象類)。

二:Timer整體類圖

在這里插入圖片描述

TimerTask類:主要為定時(shí)任務(wù)的具體內(nèi)容。

Timer類中含有3個(gè)類:Timer、TimerThread、TaskQueue。

Timer類主要是設(shè)置定時(shí)任務(wù),配置用戶期望的任務(wù)執(zhí)行時(shí)間、執(zhí)行次數(shù)、執(zhí)行內(nèi)容

TimerThread類為Thread的擴(kuò)展類,會(huì)一直從TaskQueue中獲取下標(biāo)為1的TimerTask進(jìn)行執(zhí)行。并根據(jù)該TimerTask是否需要重復(fù)執(zhí)行來決定是否放回到TaskQueue中。

TaskQueue中存放一些列將要執(zhí)行的TimerTask,以數(shù)組的形式存放,下標(biāo)約小(注:下標(biāo)為0不處理,即使用的最小下標(biāo)為1),則表明優(yōu)先級越高。

public class Timer {
    //默認(rèn)給線程命名:"Timer-" + serialNumber()
	public Timer() {
        this("Timer-" + serialNumber());
    }
    //指定Timer的名字
    public Timer(String name) {
        thread.setName(name);
        thread.start();
    }
    //isDaemon:是否為守護(hù)線程
    public Timer(boolean isDaemon) {
        this("Timer-" + serialNumber(), isDaemon);
    }
    //給定線程名字,守護(hù)線程與否
    public Timer(String name, boolean isDaemon) {
        thread.setName(name);
        //setDaemon是指定線程是否為守護(hù)線程,true是守護(hù)線程,當(dāng)主線程退出,      守護(hù)線程退出
        thread.setDaemon(isDaemon);
        thread.start();
    }    
}
//TimerThread類 繼承Thread
class TimerThread extends Thread{
	private void mainLoop() {
	......
	//每次執(zhí)行下標(biāo)為1的TimerTask
	task = queue.getMin();
	......
	}
}
//TaskQueue 類
class TaskQueue {
	//TaskQueue 中存儲(chǔ)TimerTask
    private TimerTask[] queue = new TimerTask[128];
    //返回?cái)?shù)組中下標(biāo)1的TimerTask
    TimerTask getMin() {
        return queue[1];
    }
}

三:Timer常用方法

1.Timer 類void schedule(TimerTask task, Date time)方法

1.task是定時(shí)任務(wù),time是task任務(wù)執(zhí)行時(shí)間.如果time時(shí)間早于當(dāng)前則立即執(zhí)行,否則在time時(shí)間執(zhí)行。

2.task只執(zhí)行一次,且執(zhí)行完Timer線程任務(wù)不結(jié)束,因?yàn)門imer不是守護(hù)線程,Timer timer = new Timer(true);
是指定Timer 為守護(hù)線程,當(dāng)task執(zhí)行結(jié)束后,Timer 線程會(huì)立即結(jié)束。

3.Timer 可以執(zhí)行多個(gè)定時(shí)任務(wù),TimerTask 將會(huì)按照隊(duì)列的方式一個(gè)一個(gè)被執(zhí)行,如果前面的任務(wù)耗時(shí)長,后面的任務(wù)執(zhí)行時(shí)間將會(huì)相應(yīng)的延后。

public class TimerDemo {
	//指定Timer為守護(hù)線程,run方法結(jié)束Timer線程會(huì)結(jié)束。
    private static Timer timer = new Timer(true);
    //TimerTask 具體的定時(shí)任務(wù)
    static public class MyTask extends TimerTask {
        @Override
        public void run() {
            System.out.println("已運(yùn)行,時(shí)間為:" + new Date());
        }
    }
    public static void main(String[] args) {
    	//創(chuàng)建定時(shí)任務(wù)
        MyTask myTask = new MyTask();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //早于當(dāng)前時(shí)間,定時(shí)任務(wù)會(huì)立即執(zhí)行
        String dateString = "2020-06-01 09:56:00";
        try {
            Date taskDate = sdf.parse(dateString);
            //啟動(dòng)定時(shí)任務(wù)
            timer.schedule(myTask,taskDate);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

結(jié)果:

已運(yùn)行,時(shí)間為:Wed Jul 01 14:48:06 CST 2020

2.Timer 類void schedule(TimerTask task, Date firstTime, long period)方法

TimerTask任務(wù)在指定 firstTime任務(wù)之后,周期性每隔period時(shí)間,無限期循環(huán)的執(zhí)行某一任務(wù)。

3.TimerTask 類boolean cancel()方法

TimerTask 類boolean cancel()方法,是將自身任務(wù)從任務(wù)隊(duì)列中移除。

public class TimerDemo {
    private static Timer timer = new Timer();
    static public class MyTaskA extends TimerTask {
        @Override
        public void run() {
        	//只輸出一次,MyTaskA 任務(wù)將會(huì)移除
            System.out.println("MyTaskA已運(yùn)行,時(shí)間為:" + new Date());
            //執(zhí)行TimerTask的cancel方法,將自身任務(wù)從隊(duì)列中移除
            this.cancel();
        }
    }
    static public class MyTaskB extends TimerTask {
        @Override
        public void run() {
        	//移除MyTaskA任務(wù),MyTaskB 任務(wù)不受影響
            System.out.println("MyTaskB已運(yùn)行,時(shí)間為:" + new Date());
        }
    }
    public static void main(String[] args) {
        MyTaskA myTaskA = new MyTaskA();
        MyTaskB myTaskB = new MyTaskB();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = "2020-07-01 15:19:00";
        try {
            Date taskDate = sdf.parse(dateString);
            timer.schedule(myTaskA,taskDate,2000);
            timer.schedule(myTaskB,taskDate,2000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

結(jié)果:

MyTaskA已運(yùn)行,時(shí)間為:Wed Jul 01 15:24:47 CST 2020
MyTaskB已運(yùn)行,時(shí)間為:Wed Jul 01 15:24:47 CST 2020
MyTaskB已運(yùn)行,時(shí)間為:Wed Jul 01 15:24:49 CST 2020
MyTaskB已運(yùn)行,時(shí)間為:Wed Jul 01 15:24:51 CST 2020
MyTaskB已運(yùn)行,時(shí)間為:Wed Jul 01 15:24:53 CST 2020
MyTaskB已運(yùn)行,時(shí)間為:Wed Jul 01 15:24:55 CST 2020
MyTaskB已運(yùn)行,時(shí)間為:Wed Jul 01 15:24:57 CST 2020
MyTaskB已運(yùn)行,時(shí)間為:Wed Jul 01 15:24:59 CST 2020

4.Timer 類void cancel()方法

Timer 類void cancel()方法與TimerTask 類boolean cancel()方法將自身任務(wù)從任務(wù)隊(duì)列中移除不同,它是將所有的任務(wù)都從隊(duì)列中移除。

public class TimerDemo {
    private static Timer timer = new Timer();
    static public class MyTaskA extends TimerTask {
        @Override
        public void run() {
            System.out.println("MyTaskA已運(yùn)行,時(shí)間為:" + new Date());
            //執(zhí)行Timer類的cancel方法,將Timer中所有任務(wù)從隊(duì)列中移除
            timer.cancel();
        }
    }
    static public class MyTaskB extends TimerTask {
        @Override
        public void run() {
            //MyTaskB也會(huì)被移除,因?yàn)镸yTaskA與MyTaskB是隊(duì)列執(zhí)行,先執(zhí)行MyTaskA再執(zhí)行MyTaskB
            //MyTaskA中走了timer.cancel(),所以MyTaskB不會(huì)執(zhí)行
            System.out.println("MyTaskB已運(yùn)行,時(shí)間為:" + new Date());
        }
    }
    public static void main(String[] args) {
        MyTaskA myTaskA = new MyTaskA();
        MyTaskB myTaskB = new MyTaskB();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = "2020-07-01 15:19:00";
        try {
            Date taskDate = sdf.parse(dateString);
            timer.schedule(myTaskA,taskDate,2000);
            timer.schedule(myTaskB,taskDate,2000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

結(jié)果

MyTaskA已運(yùn)行,時(shí)間為:Wed Jul 01 16:20:48 CST 2020

源碼:

public void cancel() {
        synchronized(queue) {
            thread.newTasksMayBeScheduled = false;
            queue.clear();
            queue.notify();  // In case queue was already empty.
        }
    }

執(zhí)行cancel需要搶占queue鎖,如果搶不到,則TimerTask 任務(wù)會(huì)繼續(xù)執(zhí)行。

5.Timer 類 void schedule(TimerTask task, long delay)方法

該方法以schedule(TimerTask task, long delay)方法的執(zhí)行時(shí)間為基準(zhǔn),在此時(shí)間上延遲指定的毫秒數(shù)delay后執(zhí)行一次TimerTask 任務(wù)。

6.Timer 類 void schedule(TimerTask task, long delay, long period)方法

該方法以schedule(TimerTask task, long delay, long period)方法的執(zhí)行時(shí)間為基準(zhǔn),在此時(shí)間上延遲指定的毫秒數(shù)delay后,執(zhí)行TimerTask 任務(wù),之后間隔period毫秒無限循環(huán)執(zhí)行TimerTask 任務(wù)。

7.Timer 類void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)方法

TimerTask任務(wù)在指定 firstTime任務(wù)之后,周期性每隔period時(shí)間,無限期循環(huán)的執(zhí)行某一任務(wù)。

四:重點(diǎn)

scheduleAtFixedRate(TimerTask task, Date firstTime, long period)與 schedule(TimerTask task, Date firstTime, long period)方法區(qū)別

1.相同點(diǎn):兩個(gè)方法都是按照順序執(zhí)行,無線程安全問題

2.任務(wù)不延時(shí)相同點(diǎn):如果任務(wù)執(zhí)行時(shí)間小于任務(wù)時(shí)間間隔,則第二次任務(wù)的開始時(shí)間是任務(wù)開始時(shí)間+period

3.任務(wù)延時(shí)相同點(diǎn):如果任務(wù)執(zhí)行時(shí)間大于任務(wù)時(shí)間間隔,導(dǎo)致第二次任務(wù)開始時(shí)候,上一個(gè)任務(wù)還未結(jié)束,則第二次任務(wù)的開始時(shí)間是在第一次任務(wù)結(jié)束時(shí)候立即執(zhí)行。

scheduleAtFixedRate方法與schedule方法的追趕性問題

scheduleAtFixedRate方法具有追趕性?。。?!如果計(jì)劃執(zhí)行時(shí)間早于當(dāng)前時(shí)間,執(zhí)行scheduleAtFixedRate方法后立即執(zhí)行定時(shí)任務(wù),根據(jù)任務(wù)間隔時(shí)間與當(dāng)前時(shí)間減去計(jì)劃執(zhí)行時(shí)間,補(bǔ)上之前少執(zhí)行的任務(wù)。 schedule方法不具有追趕性。?。。?!

public class TimerDemo {
    private static Timer timer = new Timer();
    static public class MyTaskA extends TimerTask {
        @Override
        public void run() {
            System.out.println("MyTaskA已運(yùn)行,時(shí)間為:" + new Date());
            try {
                //任務(wù)執(zhí)行時(shí)間是1s
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("MyTaskA已結(jié)束,時(shí)間為:" + new Date());
        }
    }
    public static void main(String[] args) {
        MyTaskA myTaskA = new MyTaskA();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = "2020-07-02 14:31:00";
        try {
            Date taskDate = sdf.parse(dateString);
            //3s執(zhí)行一次任務(wù)
            timer.scheduleAtFixedRate(myTaskA,taskDate,3000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

結(jié)果:

MyTaskA已運(yùn)行,時(shí)間為:Thu Jul 02 14:34:38 CST 2020
MyTaskA已結(jié)束,時(shí)間為:Thu Jul 02 14:34:39 CST 2020
MyTaskA已運(yùn)行,時(shí)間為:Thu Jul 02 14:34:39 CST 2020
MyTaskA已結(jié)束,時(shí)間為:Thu Jul 02 14:34:40 CST 2020
MyTaskA已運(yùn)行,時(shí)間為:Thu Jul 02 14:34:40 CST 2020
MyTaskA已結(jié)束,時(shí)間為:Thu Jul 02 14:34:41 CST 2020
MyTaskA已運(yùn)行,時(shí)間為:Thu Jul 02 14:34:41 CST 2020
MyTaskA已結(jié)束,時(shí)間為:Thu Jul 02 14:34:42 CST 2020
MyTaskA已運(yùn)行,時(shí)間為:Thu Jul 02 14:34:42 CST 2020
MyTaskA已結(jié)束,時(shí)間為:Thu Jul 02 14:34:43 CST 2020
MyTaskA已運(yùn)行,時(shí)間為:Thu Jul 02 14:34:43 CST 2020
MyTaskA已結(jié)束,時(shí)間為:Thu Jul 02 14:34:44 CST 2020
MyTaskA已運(yùn)行,時(shí)間為:Thu Jul 02 14:34:44 CST 2020
MyTaskA已結(jié)束,時(shí)間為:Thu Jul 02 14:34:45 CST 2020
MyTaskA已運(yùn)行,時(shí)間為:Thu Jul 02 14:34:45 CST 2020
MyTaskA已結(jié)束,時(shí)間為:Thu Jul 02 14:34:46 CST 2020
MyTaskA已運(yùn)行,時(shí)間為:Thu Jul 02 14:34:46 CST 2020

由上述執(zhí)行結(jié)果可知,在Thu Jul 02 14:34:38 CST 2020啟動(dòng)定時(shí)任務(wù)后,沒有間隔3s再執(zhí)行下一次任務(wù),而是任務(wù)結(jié)束就立即執(zhí)行,這是因?yàn)槿蝿?wù)計(jì)劃執(zhí)行時(shí)間早于當(dāng)前時(shí)間,需要將這期間沒有執(zhí)行的任務(wù)補(bǔ)上。

五: 總結(jié)

java中可以使用定時(shí)任務(wù)的功能,針對不同的定時(shí)任務(wù)可以根據(jù)不同的API進(jìn)行處理,從本質(zhì)來說改技術(shù)仍然屬于多線程,基于多線程實(shí)現(xiàn),不管用再多的框架實(shí)現(xiàn)定時(shí)器功能,請不要忘了這事java基礎(chǔ),框架實(shí)現(xiàn)的基礎(chǔ)。

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

相關(guān)文章

  • SpringBoot 集成 Jasypt 對數(shù)據(jù)庫加密以及踩坑的記錄分享

    SpringBoot 集成 Jasypt 對數(shù)據(jù)庫加密以及踩坑的記錄分享

    這篇文章主要介紹了SpringBoot 集成 Jasypt 對數(shù)據(jù)庫加密以及踩坑,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 利用java操作Excel文件的方法

    利用java操作Excel文件的方法

    以下是對利用java操作Excel文件的方法進(jìn)行了詳細(xì)的介紹,需要的朋友可以過來參考下
    2013-09-09
  • jstack+jdb命令查看線程及死鎖堆棧信息的實(shí)例

    jstack+jdb命令查看線程及死鎖堆棧信息的實(shí)例

    這篇文章主要介紹了jstack+jdb命令查看線程及死鎖堆棧信息的實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Json字符串內(nèi)容比較超實(shí)用教程

    Json字符串內(nèi)容比較超實(shí)用教程

    這篇文章主要介紹了Json字符串內(nèi)容比較-超實(shí)用版,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-09-09
  • Java 中的字符串常量池詳解

    Java 中的字符串常量池詳解

    本文主要介紹Java中的字符串常量池的知識(shí),這里整理了相關(guān)資料及簡單示例代碼幫助大家學(xué)習(xí)理解此部分的知識(shí),有需要的小伙伴可以參考下
    2016-09-09
  • Java中實(shí)現(xiàn)String字符串分割的3種方法

    Java中實(shí)現(xiàn)String字符串分割的3種方法

    這篇文章主要介紹了Java中實(shí)現(xiàn)String字符串分割的3種方法,文章底部介紹了JAVA?截取字符串的三種方法subString,StringUtils,split,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • intellij idea如何配置網(wǎng)絡(luò)代理

    intellij idea如何配置網(wǎng)絡(luò)代理

    intellij idea所在的這臺(tái)電腦本身上不了網(wǎng),要通過代理上網(wǎng),那么intellij idea怎么設(shè)置代理上網(wǎng)呢?今天通過本文給大家分享intellij idea如何配置網(wǎng)絡(luò)代理,感興趣的朋友一起看看吧
    2023-10-10
  • java利用StringTokenizer分割字符串的實(shí)現(xiàn)

    java利用StringTokenizer分割字符串的實(shí)現(xiàn)

    利用java.util.StringTokenizer的方法,可以將一個(gè)字符串拆分為一系列的標(biāo)記,本文就來介紹一下java利用StringTokenizer分割字符串的實(shí)現(xiàn),感興趣的可以了解一下
    2023-10-10
  • 實(shí)現(xiàn)一個(gè)簡單Dubbo完整過程詳解

    實(shí)現(xiàn)一個(gè)簡單Dubbo完整過程詳解

    這篇文章主要為大家介紹了實(shí)現(xiàn)一個(gè)簡單Dubbo完整過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • java查找圖中兩點(diǎn)之間所有路徑

    java查找圖中兩點(diǎn)之間所有路徑

    這篇文章主要為大家詳細(xì)介紹了java查找圖中兩點(diǎn)之間所有路徑,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01

最新評論