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

Java多線程定時(shí)器Timer原理及實(shí)現(xiàn)

 更新時(shí)間:2017年11月14日 16:25:06   作者:五月的倉(cāng)頡  
這篇文章主要介紹了Java多線程定時(shí)器Timer原理及實(shí)現(xiàn),涉及Timer的schedule的使用,定時(shí)器Timer的schedule等相關(guān)內(nèi)容以及代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。

前言

定時(shí)/計(jì)劃功能在Java應(yīng)用的各個(gè)領(lǐng)域都使用得非常多,比方說(shuō)Web層面,可能一個(gè)項(xiàng)目要定時(shí)采集話單、定時(shí)更新某些緩存、定時(shí)清理一批不活躍用戶等等。定時(shí)計(jì)劃任務(wù)功能在Java中主要使用的就是Timer對(duì)象,它在內(nèi)部使用多線程方式進(jìn)行處理,所以它和多線程技術(shù)關(guān)聯(lián)還是相當(dāng)大的。那和ThreadLocal一樣,還是先講原理再講使用,Timer的實(shí)現(xiàn)原理不難,就簡(jiǎn)單掃一下就好了。

Timer的schedule(TimeTask task, Date time)的使用

該方法的作用是在執(zhí)行的日期執(zhí)行一次任務(wù)

1、執(zhí)行任務(wù)的時(shí)間晚于當(dāng)前時(shí)間:未來(lái)執(zhí)行

private static Timer timer = new Timer();
static public class MyTask extends TimerTask
{
  public void run()
  {
    System.out.println("運(yùn)行了!時(shí)間為:" + new Date());
  }
}
public static void main(String[] args) throws Exception
{
  MyTask task = new MyTask();
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  String dateString = "2015-10-6 12:14:00";
  Date dateRef = sdf.parse(dateString);
  System.out.println("字符串時(shí)間:" + dateRef.toLocaleString() + " 當(dāng)前時(shí)間:" + new Date().toLocaleString());
  timer.schedule(task, dateRef);
}

看一下運(yùn)行效果:

字符串時(shí)間:2015-10-6 12:14:00 當(dāng)前時(shí)間:2015-10-6 12:13:23
運(yùn)行了!時(shí)間為:Tue Oct 06 12:14:00 CST 2015

執(zhí)行時(shí)間和但前時(shí)間不一致,而是和dateRef的時(shí)間一直,證明了未來(lái)執(zhí)行。任務(wù)雖然執(zhí)行完了,但進(jìn)程沒(méi)有銷毀,控制臺(tái)上的方框可以看到還是紅色的,看下Timer的源代碼:

public Timer() {
  this("Timer-" + serialNumber());
}
public Timer(String name) {
  thread.setName(name);
  thread.start();
}

所以,啟動(dòng)一個(gè)Timer就是啟動(dòng)一個(gè)新線程,但是這個(gè)新線程并不是守護(hù)線程,所以它會(huì)一直運(yùn)行。要運(yùn)行完就讓進(jìn)程停止的話,設(shè)置Timer為守護(hù)線程就好了,有專門的構(gòu)造函數(shù)可以設(shè)置:

public Timer(boolean isDaemon) {
  this("Timer-" + serialNumber(), isDaemon);
}
public Timer(String name, boolean isDaemon) {
  thread.setName(name);
  thread.setDaemon(isDaemon);
  thread.start();
}

2、計(jì)劃時(shí)間早于當(dāng)前時(shí)間:立即執(zhí)行

如果執(zhí)行任務(wù)的時(shí)間早于當(dāng)前時(shí)間,那么立即執(zhí)行task的任務(wù):

private static Timer timer = new Timer();
static public class MyTask extends TimerTask
{
  public void run()
  {
    System.out.println("運(yùn)行了!時(shí)間為:" + new Date());
  }
}
public static void main(String[] args) throws Exception
{
  MyTask task = new MyTask();
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  String dateString = "2014-10-6 12:14:00";
  Date dateRef = sdf.parse(dateString);
  System.out.println("字符串時(shí)間:" + dateRef.toLocaleString() + " 當(dāng)前時(shí)間:" + new Date().toLocaleString());
  timer.schedule(task, dateRef);
}

看一下運(yùn)行效果:

字符串時(shí)間:2014-10-6 12:14:00 當(dāng)前時(shí)間:2015-10-6 12:20:10
運(yùn)行了!時(shí)間為:Tue Oct 06 12:20:10 CST 2015

執(zhí)行時(shí)間和當(dāng)前時(shí)間一致,證明了立即執(zhí)行

3、多個(gè)TimerTask任務(wù)執(zhí)行

Timer中允許有多個(gè)任務(wù):

private static Timer timer = new Timer();
static public class MyTask extends TimerTask
{
  public void run()
  {
    System.out.println("運(yùn)行了!時(shí)間為:" + new Date());
  }
}
public static void main(String[] args) throws Exception
{
  MyTask task1 = new MyTask();
  MyTask task2 = new MyTask();
  SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  String dateString1 = "2015-10-6 12:26:00";
  String dateString2 = "2015-10-6 12:27:00";
  Date dateRef1 = sdf1.parse(dateString1);
  Date dateRef2 = sdf2.parse(dateString2);
  System.out.println("字符串時(shí)間:" + dateRef1.toLocaleString() + " 當(dāng)前時(shí)間:" + new Date().toLocaleString());
  System.out.println("字符串時(shí)間:" + dateRef2.toLocaleString() + " 當(dāng)前時(shí)間:" + new Date().toLocaleString());
  timer.schedule(task1, dateRef1);
  timer.schedule(task2, dateRef2);
}

看一下運(yùn)行結(jié)果:

字符串時(shí)間:2015-10-612:26:00當(dāng)前時(shí)間:2015-10-612:25:38

字符串時(shí)間:2015-10-612:27:00當(dāng)前時(shí)間:2015-10-612:25:38

運(yùn)行了!時(shí)間為:TueOct0612:26:00CST2015

運(yùn)行了!時(shí)間為:TueOct0612:27:00CST2015

可以看到,運(yùn)行時(shí)間和設(shè)置的時(shí)間一致,證明了未來(lái)可以執(zhí)行多個(gè)任務(wù)。另外注意,Task是以隊(duì)列的方式一個(gè)一個(gè)被順序執(zhí)行的,所以執(zhí)行的時(shí)間有可能和預(yù)期的時(shí)間不一致,因?yàn)榍懊娴娜蝿?wù)可能消耗過(guò)長(zhǎng),后面任務(wù)的運(yùn)行時(shí)間也有可能被延遲。

代碼就不寫了,舉個(gè)例子,任務(wù)1計(jì)劃12:00:00被執(zhí)行,任務(wù)2計(jì)劃12:00:10被執(zhí)行,結(jié)果任務(wù)1執(zhí)行了30秒,那么任務(wù)2將在12:00:30被執(zhí)行,因?yàn)門ask是被放入隊(duì)列中的,因此必須一個(gè)一個(gè)順序運(yùn)行。

Timer的schedule(TimerTasktask,DatefirstTime,longperiod)

該方法的作用是在指定的日期之后,按指定的間隔周期性地?zé)o限循環(huán)地執(zhí)行某一人物

1、計(jì)劃時(shí)間晚于當(dāng)前時(shí)間:未來(lái)執(zhí)行

static public class MyTask extends TimerTask
{
  public void run()
  {
    System.out.println("運(yùn)行了!時(shí)間為:" + new Date());
  }
}
public static void main(String[] args) throws Exception
{
  MyTask task = new MyTask();
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  String dateString = "2015-10-6 18:00:00";
  Timer timer = new Timer();
  Date dateRef = sdf.parse(dateString);
  System.out.println("字符串時(shí)間:" + dateRef.toLocaleString() + " 當(dāng)前時(shí)間:" + new Date().toLocaleString());
  timer.schedule(task, dateRef, 4000);
}

看一下運(yùn)行結(jié)果:

字符串時(shí)間:2015-10-6 18:01:00 當(dāng)前時(shí)間:2015-10-6 18:00:15
運(yùn)行了!時(shí)間為:Tue Oct 06 18:01:00 CST 2015
運(yùn)行了!時(shí)間為:Tue Oct 06 18:01:04 CST 2015
運(yùn)行了!時(shí)間為:Tue Oct 06 18:01:08 CST 2015
運(yùn)行了!時(shí)間為:Tue Oct 06 18:01:12 CST 2015
...

看到從設(shè)定的時(shí)間開(kāi)始,每隔4秒打印一次,無(wú)限打印下去

2、計(jì)劃時(shí)間早于當(dāng)前時(shí)間:立即執(zhí)行

static public class MyTask extends TimerTask
{
  public void run()
  {
    System.out.println("運(yùn)行了!時(shí)間為:" + new Date());
  }
}
public static void main(String[] args) throws Exception
{
  MyTask task = new MyTask();
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  String dateString = "2014-10-6 18:01:00";
  Timer timer = new Timer();
  Date dateRef = sdf.parse(dateString);
  System.out.println("字符串時(shí)間:" + dateRef.toLocaleString() + " 當(dāng)前時(shí)間:" + new Date().toLocaleString());
  timer.schedule(task, dateRef, 4000);
}

看一下運(yùn)行結(jié)果:

字符串時(shí)間:2014-10-6 18:01:00 當(dāng)前時(shí)間:2015-10-6 18:02:46
運(yùn)行了!時(shí)間為:Tue Oct 06 18:02:46 CST 2015
運(yùn)行了!時(shí)間為:Tue Oct 06 18:02:50 CST 2015
運(yùn)行了!時(shí)間為:Tue Oct 06 18:02:54 CST 2015
運(yùn)行了!時(shí)間為:Tue Oct 06 18:02:58 CST 2015
運(yùn)行了!時(shí)間為:Tue Oct 06 18:03:02 CST 2015
...

看到運(yùn)行時(shí)間比當(dāng)前時(shí)間早,從當(dāng)前時(shí)間開(kāi)始,每隔4秒打印一次,無(wú)限循環(huán)下去

TimerTask的cancel()方法

TimerTask的cancel()方法的作用是將自身從任務(wù)隊(duì)列中清除:

static public class MyTaskA extends TimerTask
{
  public void run()
  {
    System.out.println("A運(yùn)行了!時(shí)間為:" + new Date());
    this.cancel();
  }
}
  
static public class MyTaskB extends TimerTask
{
  public void run()
  {
    System.out.println("B運(yùn)行了!時(shí)間為:" + new Date());
  }
}
  
public static void main(String[] args) throws Exception
{
  MyTaskA taskA = new MyTaskA();
  MyTaskB taskB = new MyTaskB();
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  String dateString = "2015-10-6 18:10:00";
  Timer timer = new Timer();
  Date dateRef = sdf.parse(dateString);
  System.out.println("字符串時(shí)間:" + dateRef.toLocaleString() + " 當(dāng)前時(shí)間:" + new Date().toLocaleString());
  timer.schedule(taskA, dateRef, 4000);
  timer.schedule(taskB, dateRef, 4000);  
}

看一下運(yùn)行結(jié)果:

字符串時(shí)間:2015-10-6 18:10:00 當(dāng)前時(shí)間:2015-10-6 18:09:47
A運(yùn)行了!時(shí)間為:Tue Oct 06 18:10:00 CST 2015
B運(yùn)行了!時(shí)間為:Tue Oct 06 18:10:00 CST 2015
B運(yùn)行了!時(shí)間為:Tue Oct 06 18:10:04 CST 2015
B運(yùn)行了!時(shí)間為:Tue Oct 06 18:10:08 CST 2015
B運(yùn)行了!時(shí)間為:Tue Oct 06 18:10:12 CST 2015
...

看到TimeTask的cancel()方法是將自身從任務(wù)隊(duì)列中被移除,其他任務(wù)不受影響

Timer的cancel()方法

把上面代碼改動(dòng)一下:

private static Timer timer = new Timer();
  
static public class MyTaskA extends TimerTask
{
  public void run()
  {
    System.out.println("A運(yùn)行了!時(shí)間為:" + new Date());
    timer.cancel();
  }
}
  
static public class MyTaskB extends TimerTask
{
  public void run()
  {
    System.out.println("B運(yùn)行了!時(shí)間為:" + new Date());
  }
}
  
public static void main(String[] args) throws Exception
{
  MyTaskA taskA = new MyTaskA();
  MyTaskB taskB = new MyTaskB();
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  String dateString = "2015-10-6 18:10:00";
  Date dateRef = sdf.parse(dateString);
  System.out.println("字符串時(shí)間:" + dateRef.toLocaleString() + " 當(dāng)前時(shí)間:" + new Date().toLocaleString());
  timer.schedule(taskA, dateRef, 4000);
  timer.schedule(taskB, dateRef, 4000);
}

看一下運(yùn)行結(jié)果:

字符串時(shí)間:2015-10-618:10:00當(dāng)前時(shí)間:2015-10-618:14:15

A運(yùn)行了!時(shí)間為:TueOct0618:14:15CST2015

全部任務(wù)都被清除,并且進(jìn)程被銷毀。不過(guò)注意一下,cancel()方法未必一定會(huì)停止執(zhí)行計(jì)劃任務(wù),可能正常執(zhí)行,因?yàn)閏ancel()方法會(huì)嘗試去獲取queue鎖,如果并沒(méi)有獲取到queue鎖的話,TimerTask類中的任務(wù)繼續(xù)執(zhí)行也是完全有可能的

其他方法

再列舉一些Timer中的其他schedule的重載方法的作用,就不提供證明的代碼了,可以自己嘗試一下:

1、schedule(TimerTasktask,longdelay)

以當(dāng)前時(shí)間為參考,在此時(shí)間基礎(chǔ)上延遲指定的毫秒數(shù)后執(zhí)行一次TimerTask任務(wù)

2、schedule(TimerTasktask,longdelay,longperiod)

以當(dāng)前時(shí)間為參考,在此時(shí)間基礎(chǔ)上延遲指定的毫秒數(shù)后,以period為循環(huán)周期,循環(huán)執(zhí)行TimerTask任務(wù)

3、scheduleAtFixedRate(TimerTasktask,DatefirstTime,longperiod)

在延時(shí)的場(chǎng)景下,schedule方法和scheduleAtFixedRate方法沒(méi)有區(qū)別,它們的區(qū)別只是在非延時(shí)上。如果執(zhí)行任務(wù)的時(shí)間沒(méi)有被延時(shí),對(duì)于schedule方法來(lái)說(shuō),下一次任務(wù)執(zhí)行的時(shí)間參考的是上一次任務(wù)的開(kāi)始時(shí)間來(lái)計(jì)算的;對(duì)于scheduleAtFixedRate方法來(lái)說(shuō),下一次任務(wù)執(zhí)行的時(shí)間參考的是上一次任務(wù)的結(jié)束時(shí)間來(lái)計(jì)算的

總結(jié)

以上就是本文關(guān)于Java多線程定時(shí)器Timer原理及實(shí)現(xiàn)的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:

java多線程編程實(shí)例

淺談Java多線程的優(yōu)點(diǎn)及代碼示例

Java多線程之readwritelock讀寫分離的實(shí)現(xiàn)代碼

如有不足之處,歡迎留言指出。

相關(guān)文章

  • Java?Valhalla?Project項(xiàng)目介紹

    Java?Valhalla?Project項(xiàng)目介紹

    這篇文章主要介紹了Java?Valhalla?Project項(xiàng)目介紹,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • 關(guān)于Mybatis實(shí)體別名支持通配符掃描問(wèn)題小結(jié)

    關(guān)于Mybatis實(shí)體別名支持通配符掃描問(wèn)題小結(jié)

    MyBatis可以使用簡(jiǎn)單的 XML 或注解來(lái)配置和映射原生信息,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對(duì)象)映射成數(shù)據(jù)庫(kù)中的記錄,這篇文章主要介紹了Mybatis實(shí)體別名支持通配符掃描的問(wèn)題,需要的朋友可以參考下
    2022-01-01
  • Java操作minio刪除文件夾及其文件方法(MinIO基本使用)

    Java操作minio刪除文件夾及其文件方法(MinIO基本使用)

    MinIO是一個(gè)高性能、無(wú)限擴(kuò)展的開(kāi)源對(duì)象存儲(chǔ)服務(wù)器,它以對(duì)象的形式存儲(chǔ)數(shù)據(jù),并兼容Amazon S3接口,它適用于大規(guī)模數(shù)據(jù)存儲(chǔ)、大數(shù)據(jù)分析、文件共享和備份等應(yīng)用場(chǎng)景,這篇文章主要介紹了java操作minio刪除文件夾及其文件方法,需要的朋友可以參考下
    2024-02-02
  • SSM項(xiàng)目中配置LOG4J日志的方法

    SSM項(xiàng)目中配置LOG4J日志的方法

    本篇文章主要介紹了SSM項(xiàng)目中配置LOG4J日志的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09
  • Java8新特性之lambda的作用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java8新特性之lambda的作用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    我們期待了很久lambda為java帶來(lái)閉包的概念,但是如果我們不在集合中使用它的話,就損失了很大價(jià)值。現(xiàn)有接口遷移成為lambda風(fēng)格的問(wèn)題已經(jīng)通過(guò)default methods解決了,在這篇文章將深入解析Java集合里面的批量數(shù)據(jù)操作解開(kāi)lambda最強(qiáng)作用的神秘面紗。
    2017-06-06
  • 全面解析Java中的HashMap類

    全面解析Java中的HashMap類

    HashMap類為Java提供了鍵值對(duì)應(yīng)的map類型,本文將從源碼角度全面解析Java中的HashMap類,同時(shí)包括其各種常用操作方法等,歡迎參考與借鑒
    2016-05-05
  • Java高級(jí)特性基礎(chǔ)之反射五連問(wèn)

    Java高級(jí)特性基礎(chǔ)之反射五連問(wèn)

    反射賦予了我們?cè)谶\(yùn)行時(shí)分析類以及執(zhí)行類中方法的能力。通過(guò)反射你可以獲取任意一個(gè)類的所有屬性和方法,你還可以調(diào)用這些方法和屬性。本文就來(lái)和大家詳細(xì)聊聊Java中的反射,感興趣的可以了解一下
    2023-01-01
  • MyBatis-Plus中的邏輯刪除使用詳解

    MyBatis-Plus中的邏輯刪除使用詳解

    開(kāi)發(fā)系統(tǒng)時(shí),有時(shí)候在實(shí)現(xiàn)功能時(shí),刪除操作需要實(shí)現(xiàn)邏輯刪除就是將數(shù)據(jù)標(biāo)記為刪除,而并非真的物理刪除(非DELETE操作),查詢時(shí)需要攜帶狀態(tài)條件,確保被標(biāo)記的數(shù)據(jù)不被查詢到。這樣做的目的就是避免數(shù)據(jù)被真正的刪除
    2022-12-12
  • java中g(shù)c算法實(shí)例用法

    java中g(shù)c算法實(shí)例用法

    在本篇文章里小編給大家整理了一篇關(guān)于java中g(shù)c算法實(shí)例用法,有興趣的朋友們可以參考學(xué)習(xí)下。
    2021-01-01
  • Java中如何編寫一個(gè)數(shù)的n次方(冪運(yùn)算)?

    Java中如何編寫一個(gè)數(shù)的n次方(冪運(yùn)算)?

    本文介紹了使用pow函數(shù)和自定義for循環(huán)計(jì)算冪的O(n)時(shí)間復(fù)雜度方法,然后重點(diǎn)講解了快速冪算法的分治思想,以及從二進(jìn)制角度的解釋,包括如何通過(guò)位運(yùn)算和循環(huán)迭代實(shí)現(xiàn)高效計(jì)算,給出了Java代碼實(shí)現(xiàn)
    2024-07-07

最新評(píng)論

榆林市| 辽源市| 三亚市| 岑巩县| 三穗县| 太康县| 大连市| 文安县| 福海县| 涪陵区| 洛扎县| 太和县| 彰武县| 神池县| 吉安县| 宿州市| 洛南县| 碌曲县| 基隆市| 临颍县| 长子县| 南丹县| 固安县| 长宁县| 台江县| 长泰县| 中牟县| 东丰县| 隆昌县| 丹阳市| 射洪县| 隆林| 禄劝| 桃源县| 蚌埠市| 呈贡县| 渑池县| 高密市| 泾源县| 安溪县| 湖州市|