亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java線程中的Timer和TimerTask原理詳解

 更新時(shí)間:2023年10月10日 08:31:07   作者:zhangbeizhen18  
這篇文章主要介紹了Java線程中的Timer和TimerTask原理詳解,Timer和TimerTask成對(duì)出現(xiàn),Timer是定時(shí)器,TimerTask是定時(shí)任務(wù),換句話說,定時(shí)任務(wù)TimerTask是給定時(shí)器Timer執(zhí)行的具體任務(wù),需要的朋友可以參考下

前言

場(chǎng)景:Java JDK自帶的定時(shí)器Timer和定時(shí)任務(wù)TimerTask應(yīng)用以及原理簡(jiǎn)析。

在JDK工具包:java.util中可以找到源碼,即java.util.Timer和java.util.TimerTask。

TimerTask實(shí)現(xiàn)Runnable接口的run方法。Timer的屬性TimerThread thread繼承Thread。

因此,Timer天生就具備多線程屬性。這個(gè)輕量級(jí)的定時(shí)器和定時(shí)任務(wù),在多線程的場(chǎng)景中使用極其便利和靈活。

版本:

JDK 1.8
Spring Boot 2.6.3
Spring Framework 5.3.15

1.基礎(chǔ)

Timer和TimerTask成對(duì)出現(xiàn),Timer是定時(shí)器,TimerTask是定時(shí)任務(wù)。換句話說,定時(shí)任務(wù)TimerTask是給定時(shí)器Timer執(zhí)行的具體任務(wù)。在JDK 1.8中TimerTask是抽象類(abstract),使用者繼承TimerTask,并實(shí)現(xiàn)抽象方法run()方法即可。TimerTask實(shí)現(xiàn)Runnable接口的run()。

1.1 TimerTask

TimerTask,即java.util.TimerTask,一個(gè)抽象類(abstract修飾的類),實(shí)現(xiàn)(implements)可被線程執(zhí)行的Runnable接口。

TimerTask需關(guān)注的內(nèi)容。

(1)屬性:final Object lock,多線程同步時(shí)使用。在Timer的TimerThread中同步鎖synchronized會(huì)使用。

(2)屬性:int state,標(biāo)識(shí)TimerTask的當(dāng)前狀態(tài)。包括VIRGIN,SCHEDULED,EXECUTED,CANCELLED。

(3)屬性:long nextExecutionTime,下一次執(zhí)行的時(shí)間。

(4)屬性:long period,重復(fù)任務(wù)的執(zhí)行頻率。

(5)方法:boolean cancel(),取消任務(wù),實(shí)際標(biāo)記任務(wù)狀態(tài)state為CANCELLED。

(6)方法:scheduledExecutionTime(),獲取調(diào)度時(shí)間。

(7)方法:protected TimerTask(),無參構(gòu)造方法。

(8)方法:abstract void run(),線程執(zhí)行具體函數(shù),使用者的具體業(yè)務(wù)任務(wù)就在這個(gè)方法中寫。

1.2 TaskQueue

TaskQueue,即java.util.TaskQueue。TaskQueue維護(hù)一個(gè)屬性TimerTask[] queue,這是Timer的任務(wù)線程操作的底層隊(duì)列。在Timer中有TaskQueue屬性,是給任務(wù)線程TimerThread使用的。

TaskQueue需關(guān)注的內(nèi)容。

(1)屬性:TimerTask[] queue,隊(duì)列中存放TimerTask。Timer的TimerThread通過遍歷queue,取出TimerTask,根據(jù)TimerTask屬性來確定當(dāng)前是否執(zhí)行。。

注意:使用者不需要直接操作TimerTask[] queue,它是交給Timer的TimerThread操作。

1.3 TimerThread

TimerThread,即java.util.TimerThread。繼承Thread類。因此,天生就具備多線程屬性。

TimerThread需關(guān)注的內(nèi)容。

(1)屬性:TaskQueue queue,TimerThread操作queue來找到當(dāng)前需要執(zhí)行的定時(shí)任務(wù)TimerTask。根據(jù)執(zhí)行策略執(zhí)行定時(shí)任務(wù)TimerTask中的run方法。

(2)方法:void run(),是TimerThread從Thread中繼承的方法。線程執(zhí)行的具體內(nèi)容,必須在這個(gè)方法中寫入或者在這個(gè)方法中被調(diào)用。TimerThread實(shí)現(xiàn)細(xì)節(jié)方法是void mainLoop()。在run方法中會(huì)調(diào)用mainLoop(),這樣定時(shí)任務(wù)就被任務(wù)線程調(diào)用到。

(3)方法:void mainLoop(),TimerThread中邏輯細(xì)節(jié)落地方法。本方法內(nèi)容在while (true)中,只要隊(duì)列有任務(wù)就會(huì)無限循環(huán)。方法核心內(nèi)容就是遍歷TimerThread的屬性:TaskQueue queue,找到符合條件的需執(zhí)行的TimerTask,并執(zhí)行TimerTask的run方法。

(4)方法: void start(),此方法是TimerThread從Thread繼承來的,作用就是啟動(dòng)線程。TimerThread的start()方在Timer創(chuàng)建時(shí)就會(huì)調(diào)用。Timer創(chuàng)建后,TimerThread就啟動(dòng)了。

1.4 Timer

Timer,即java.util.Timer。使用者操定時(shí)器就是操作這個(gè)類的任務(wù)調(diào)度方法。

Timer的需關(guān)注的內(nèi)容。

(1)屬性:final TaskQueue queue,Timer存放所有的定時(shí)任務(wù)的隊(duì)列,定時(shí)器Timer的核心就是遍歷這個(gè)隊(duì)列,找到當(dāng)前時(shí)間下,符合條件的需執(zhí)行的定時(shí)任務(wù)TimerTask。

(2)屬性:final TimerThread thread,Timer執(zhí)行定時(shí)任務(wù)的后臺(tái)線程。定時(shí)任務(wù)具體執(zhí)行邏輯在TimerThread的run方法中。TimerThread 線程在Timer的構(gòu)造函數(shù)中會(huì)調(diào)用TimerThread的start()啟動(dòng)線程。

(3)構(gòu)造函數(shù)

  • Timer(),無參構(gòu)造函數(shù)。
  • Timer(boolean isDaemon),有參構(gòu)造函數(shù)。設(shè)置定時(shí)器線程是否為守護(hù)線程。就是設(shè)置屬性:TimerThread thread,調(diào)用Thread的setDaemon()方法。
  • Timer(String name),有參構(gòu)造函數(shù)。設(shè)置線程名稱。
  • Timer(String name, boolean isDaemon)。有參構(gòu)造函數(shù)。設(shè)置線程名稱和設(shè)置是否為守護(hù)線程。

(4)任務(wù)調(diào)度函數(shù)

任務(wù)調(diào)度函數(shù)

操作Timer定時(shí)器,實(shí)際就是操作如下任務(wù)調(diào)度函數(shù)。

public void schedule(TimerTask task, long delay);
public void schedule(TimerTask task, Date time);
public void schedule(TimerTask task, long delay, long period);
public void schedule(TimerTask task, Date firstTime, long period); 
public void scheduleAtFixedRate(TimerTask task, long delay, long period);
public void scheduleAtFixedRate(TimerTask task, Date firstTime,long period);

任務(wù)調(diào)度函數(shù)(sched)

任務(wù)調(diào)度函數(shù)都會(huì)調(diào)用一個(gè)私有方法sched。

private void sched(TimerTask task, long time, long period);

TimerTask task:繼承抽象類TimerTask,重寫abstract void run()方法,把具體業(yè)務(wù)任務(wù)寫在這個(gè)方法里。

long time:調(diào)度任務(wù)的起始時(shí)間值。調(diào)度是從這個(gè)時(shí)間為計(jì)算起點(diǎn)。

long period:任務(wù)調(diào)度頻率。

把定時(shí)任務(wù)TimerTask添加到隊(duì)列,就是在這個(gè)方法中實(shí)現(xiàn)。

(5)方法:void cancel(),取消隊(duì)列里所有任務(wù)。

(6)方法:void purge(),清除隊(duì)列里所有任務(wù)。

2.Timer原理解析

Timer原理解析,來自JDK中java.util.Timer源碼邏輯。如有疑惑,可直接翻閱源碼,便一目了然。

2.1 添加定時(shí)任務(wù)

把TimerTask添加到Timer內(nèi)部的TaskQueue中。

2.2.1 自定義實(shí)現(xiàn)TimerTask的 run()

自定義實(shí)現(xiàn)抽象類TimerTask的 run()方法,即任務(wù)需要執(zhí)行的業(yè)務(wù)邏輯寫在run方法中。

2.2.2 創(chuàng)建定時(shí)器Timer

創(chuàng)建定時(shí)器Timer,會(huì)做三件核心事情。

(1)創(chuàng)建任務(wù)隊(duì)列:TaskQueue queue。

(2)創(chuàng)建定時(shí)器線程:TimerThread thread。

(3)啟動(dòng)定時(shí)器線程:執(zhí)行TimerThread的start()方法,即后臺(tái)循環(huán)掃描的定時(shí)器線程啟動(dòng)。

2.2.3 調(diào)用Timer任務(wù)調(diào)度函數(shù)

添加定時(shí)任務(wù)就在調(diào)用Timer任務(wù)調(diào)度方法中完成。

(1)設(shè)置定時(shí)器任務(wù)調(diào)度參數(shù)。

(2)把自定義任務(wù)傳遞給任務(wù)調(diào)度函數(shù)。

2.2.4 Timer任務(wù)調(diào)度函數(shù)核心邏輯

Timer暴露給使用者的所有任務(wù)調(diào)度函數(shù),最終都會(huì)落地在一個(gè)私有方法,即

void sched(TimerTask task, long time, long period);

核心邏輯如下:

(1)同步鎖:synchronized(queue),鎖住隊(duì)列。隊(duì)列所有操作在此鎖內(nèi)完成。

(2)同步鎖:synchronized(task.lock),鎖住任務(wù)。

此鎖內(nèi)主要操作:設(shè)置TimerTask任務(wù)的執(zhí)行時(shí)間,執(zhí)行頻率,任務(wù)狀態(tài)。操作完成立即解鎖。

(3)隊(duì)列TaskQueue queue,把設(shè)置好的TimerTask添加到TaskQueue 中。

(4)解除同步鎖:synchronized(queue)。

2.2 執(zhí)行定時(shí)任務(wù)

執(zhí)行定時(shí)任務(wù),在Timer的定時(shí)器線程TimerThread thread中,即線程的run()方法中,最終落地方式是 mainLoop()。注意mainLoop()是在run()方法中調(diào)用,是邏輯集中寫在mainLoop()中,增加代碼易讀性。

2.2.1 while (true)入口

mainLoop()入口是while (true),即使循環(huán)掃描。

2.2.2 同步鎖:synchronized(queue)

同步鎖:synchronized(queue),鎖住隊(duì)列,一個(gè)Timer共用一個(gè)隊(duì)列,因此使用synchronized有效。

2.2.3 判斷隊(duì)列是否為空

使用 while (queue.isEmpty() && newTasksMayBeScheduled)判斷隊(duì)列是否為空,如果為空,則 queue.wait()等待,注意wait()是java.lang.Object的方法,因此,此時(shí)while在卡主狀態(tài),直到queue.notify()被調(diào)用,才會(huì)繼續(xù)。

2.2.4 確認(rèn)隊(duì)列為空跳出循環(huán)

使用if (queue.isEmpty()),判斷隊(duì)列確定為空了,那么就break跳出循環(huán),其實(shí)任務(wù)線程就優(yōu)雅結(jié)束了。

2.2.5 取出一個(gè)任務(wù)TimerTask

取出一個(gè)任務(wù):task = queue.getMin();

2.2.6 同步鎖:synchronized(task.lock),操作任務(wù)

使用同步鎖:synchronized(task.lock),鎖住任務(wù)。判斷任務(wù)是否可執(zhí)行。

(1)判斷任務(wù)狀態(tài)。

(2)取當(dāng)前系統(tǒng)時(shí)間:System.currentTimeMillis()。

(3)取出的任務(wù)執(zhí)行時(shí)間: task.nextExecutionTime。

(4)判斷當(dāng)前系統(tǒng)時(shí)間和任務(wù)執(zhí)行時(shí)間,來確定任務(wù)是否需要執(zhí)行。

(5)使用任務(wù)狀態(tài)標(biāo)識(shí)taskFired=true任務(wù)需啟動(dòng);否則,不啟動(dòng)。。

(6)任務(wù)操作完成,解除同步鎖:synchronized(task.lock)。

2.2.7 解除同步鎖:synchronized(queue)

2.2.8 執(zhí)行任務(wù):task.run()。

自定義的定時(shí)任務(wù)TimerTask,在此處就被執(zhí)行。

3.案例

本例每隔60秒,獲取一次UUID。

(1)實(shí)現(xiàn)TimerTask的run方法,把具體執(zhí)行的業(yè)務(wù)任務(wù)寫到run方法中。

(2)創(chuàng)建Timer對(duì)象,配置定時(shí)任務(wù)和傳入TimerTask對(duì)象。

Timer提供多種任務(wù)調(diào)度策略,本例使用固定頻率任務(wù)調(diào)度。

TimeMonitor,實(shí)現(xiàn)了InitializingBean接口,在afterPropertiesSet中初始化定時(shí)器。也就是TimeMonitor被容器初始化完成后,就會(huì)觸發(fā)Timer定時(shí)器初始化,Timer定時(shí)器內(nèi)部的任務(wù)線程會(huì)啟動(dòng)和任務(wù)隊(duì)列會(huì)把使用者的定時(shí)任務(wù)添加到隊(duì)列。Timer定時(shí)器就會(huì)生效運(yùn)行。

@Slf4j
@Service
public class TimeMonitor implements InitializingBean {
  @Override
  public void afterPropertiesSet() throws Exception {
      startTimerMonitor();
  }
  private void startTimerMonitor() {
    TimerTask timerTask = new TimerTask() {
      @Override
      public void run() {
          log.info("定時(shí)任務(wù)執(zhí)行開始.");
          String uuid = UUID.randomUUID().toString()
              .replace("-", "").toUpperCase();
          log.info("執(zhí)行業(yè)務(wù),獲取序列號(hào),UUID = " + uuid);
          log.info("定時(shí)任務(wù)執(zhí)行完成.");
      }
    };
    // 定時(shí)器
    Timer timer = new Timer();
    // 延時(shí)時(shí)間
    long delayTime = 6000L;
    // 執(zhí)行頻率
    long period = 1000 * 60;
    timer.scheduleAtFixedRate(timerTask, delayTime, period);
  }
}

4.測(cè)試

根據(jù)輸出日志查看定時(shí)調(diào)度情況。

到此這篇關(guān)于Java線程中的Timer和TimerTask原理詳解的文章就介紹到這了,更多相關(guān)Java的Timer和TimerTask內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot整合MD5加密完成注冊(cè)和登錄方式

    SpringBoot整合MD5加密完成注冊(cè)和登錄方式

    MD5(MessageDigestAlgorithm5)是一種常見的哈希算法,用于生成固定長(zhǎng)度(128位)的哈希值,主要應(yīng)用于數(shù)據(jù)完整性校驗(yàn)和密碼存儲(chǔ),MD5具有快速計(jì)算、不可逆性和抗碰撞性等特點(diǎn),盡管存在碰撞漏洞,MD5仍廣泛應(yīng)用于文件下載校驗(yàn)和數(shù)字簽名等場(chǎng)景
    2024-10-10
  • Java中Elasticsearch 實(shí)現(xiàn)分頁方式(三種方式)

    Java中Elasticsearch 實(shí)現(xiàn)分頁方式(三種方式)

    Elasticsearch是用Java語言開發(fā)的,并作為Apache許可條款下的開放源碼發(fā)布,是一種流行的企業(yè)級(jí)搜索引擎,這篇文章主要介紹了Elasticsearch實(shí)現(xiàn)分頁的3種方式,需要的朋友可以參考下
    2022-07-07
  • 簡(jiǎn)潔實(shí)用的Java Base64編碼加密異常處理類代碼

    簡(jiǎn)潔實(shí)用的Java Base64編碼加密異常處理類代碼

    這篇文章主要介紹了簡(jiǎn)潔實(shí)用的Java Base64編碼加密異常處理類代碼,有一定的實(shí)用價(jià)值,需要的朋友可以參考下
    2014-07-07
  • 一篇文章搞定數(shù)據(jù)庫連接池

    一篇文章搞定數(shù)據(jù)庫連接池

    數(shù)據(jù)庫連接池在編寫應(yīng)用服務(wù)是經(jīng)常需要用到的模塊,太過頻繁的連接數(shù)據(jù)庫對(duì)服務(wù)性能來講是一個(gè)瓶頸,使用緩沖池技術(shù)可以來消除這個(gè)瓶頸,本文就來介紹Java常見的幾種,感興趣的可以了解一下
    2021-07-07
  • 如何實(shí)現(xiàn)Java中一個(gè)簡(jiǎn)單的LinkedList

    如何實(shí)現(xiàn)Java中一個(gè)簡(jiǎn)單的LinkedList

    LinkedList與ArrayList都是List接口的具體實(shí)現(xiàn)類。下面將介紹如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的LinkedList,具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-02-02
  • Java構(gòu)造函數(shù)與普通函數(shù)用法詳解

    Java構(gòu)造函數(shù)與普通函數(shù)用法詳解

    本篇文章給大家詳細(xì)講述了Java構(gòu)造函數(shù)與普通函數(shù)用法以及相關(guān)知識(shí)點(diǎn),對(duì)此有興趣的朋友可以參考學(xué)習(xí)下。
    2018-03-03
  • 探討Java 將Markdown文件轉(zhuǎn)換為Word和PDF文檔

    探討Java 將Markdown文件轉(zhuǎn)換為Word和PDF文檔

    這篇文章主要介紹了Java 將Markdown文件轉(zhuǎn)換為Word和PDF文檔,本文通過分步指南及代碼示例展示了如何將 Markdown 文件轉(zhuǎn)換為 Word 文檔和 PDF 文件,需要的朋友可以參考下
    2024-07-07
  • springboot中.yml文件參數(shù)的讀取方式

    springboot中.yml文件參數(shù)的讀取方式

    這篇文章主要介紹了springboot中.yml文件參數(shù)的讀取方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java讀取圖片EXIF信息的方法

    Java讀取圖片EXIF信息的方法

    這篇文章主要介紹了Java讀取圖片EXIF信息的方法,較為詳細(xì)的分析了圖片EXIF信息的概念、功能及java讀取EXIF信息的實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2015-07-07
  • 基于javaWeb 項(xiàng)目SSM配置要點(diǎn)及可能遇到的問題和解決方法

    基于javaWeb 項(xiàng)目SSM配置要點(diǎn)及可能遇到的問題和解決方法

    下面小編就為大家?guī)硪黄趈avaWeb 項(xiàng)目SSM配置要點(diǎn)及可能遇到的問題和解決方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10

最新評(píng)論