java中的Timer和Timertask的關(guān)系解讀
一 time和timertask的關(guān)系
1.1 timer和timertask關(guān)系
1.Timer來(lái)講就是一個(gè)調(diào)度器,而TimerTask呢只是一個(gè)實(shí)現(xiàn)了run方法的一個(gè)類(lèi);
2.Timer和TimerTask成對(duì)出現(xiàn),Timer是定時(shí)器,TimerTask是定時(shí)任務(wù)。換句話說(shuō),定時(shí)任務(wù)TimerTask是給定時(shí)器Timer執(zhí)行的具體任務(wù)。TimerTask實(shí)現(xiàn)Runnable接口的run方法。
Java的定時(shí)器Timer和定時(shí)任務(wù)TimerTask應(yīng)用以及原理
3.每一個(gè)Timer僅對(duì)應(yīng)唯一一個(gè)線程。Timer不保證任務(wù)執(zhí)行的十分精確。Timer類(lèi)的線程安全的。
4.一個(gè)Timer可以調(diào)度任意多個(gè)TimerTask,所有任務(wù)都存儲(chǔ)在一個(gè)隊(duì)列中順序執(zhí)行,如果需要多個(gè)TimerTask并發(fā)執(zhí)行,則需要?jiǎng)?chuàng)建兩個(gè)多個(gè)Timer。
一個(gè)Timer可以執(zhí)行多個(gè)TimerTask,但一個(gè)TimerTask只能被一個(gè)Timer使用(這和schedule中校驗(yàn)TimerTask的狀態(tài)有關(guān),TimerTask的生命周期(由不同的狀態(tài)確定))。
簡(jiǎn)單的說(shuō)Timer中有兩個(gè)核心部分:
TimerThread是時(shí)間線程,控制TaskQueue中TimerTask的執(zhí)行;
TaskQueue是一個(gè)工具類(lèi),管理TimerTask數(shù)組

1.2 timer的api
無(wú)參構(gòu)造方法,簡(jiǎn)單通過(guò)Tiemer為前綴構(gòu)造一個(gè)線程名稱(chēng)

有參構(gòu)造方法,傳入了是否為后臺(tái)線程,后臺(tái)線程當(dāng)且僅當(dāng)進(jìn)程結(jié)束時(shí),自動(dòng)注銷(xiāo)掉。

1.3 終止Timer線程
默認(rèn)情況下,創(chuàng)建的timer線程會(huì)一直執(zhí)行,主要有下面四種方式來(lái)終止timer線程:
1) 調(diào)用Timer.cancle()方法??梢栽诔绦蛉魏蔚胤秸{(diào)用,甚至在TimerTask中的run方法中調(diào)用;
2) 創(chuàng)建Timer時(shí)定義位daemon守護(hù)線程,使用new Timer(true)語(yǔ)句;
3) 設(shè)置Timer對(duì)象為null,其會(huì)自動(dòng)終止;????有待考證
4) 調(diào)用System.exit方法,整個(gè)程序終止。
1.4 timer注意事項(xiàng)
1) Timer線程不會(huì)捕獲異常,所以TimerTask拋出的未檢查的異常會(huì)終止timer線程。如果Timer線程中存在多個(gè)計(jì)劃任務(wù),其中一個(gè)計(jì)劃任務(wù)拋出未檢查的異常,則會(huì)引起整個(gè)Timer線程結(jié)束,從而導(dǎo)致其他計(jì)劃任務(wù)無(wú)法得到繼續(xù)執(zhí)行?! ?/p>
2) Timer線程時(shí)基于絕對(duì)時(shí)間(如:2023/02/14 16:06:00),因此計(jì)劃任務(wù)對(duì)系統(tǒng)的時(shí)間的改變是敏感的。
3) Timer是單線程,如果某個(gè)任務(wù)很耗時(shí),可能會(huì)影響其他計(jì)劃任務(wù)的執(zhí)行。
因此,JDK1.5以上建議使用ScheduledThreadPoolExecutor來(lái)代替Timer執(zhí)行計(jì)劃任務(wù)。
二 操作案例
2.1 一個(gè)Timer執(zhí)行多個(gè)Task,堵塞現(xiàn)象
package com.ljf.lockdemo.task.timerdemo;
import java.util.Timer;
import java.util.TimerTask;
/**
* @ClassName: TestDemo2
* @Description: TODO
* @Author: admin
* @Date: 2024/03/02 11:30:06
* @Version: V1.0
**/
public class TestDemo2 {
public static void main(String[] args) {
TimerTask task1=new TimerTask() {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println("[當(dāng)前線程是:"+name+",執(zhí)行定時(shí)任務(wù)1:"+System.currentTimeMillis()+"]");
}
};
TimerTask task2=new TimerTask() {
@Override
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println("[當(dāng)前線程是:"+name+",執(zhí)行定時(shí)任務(wù)2:"+System.currentTimeMillis()+"]");
}
};
Timer timer=new Timer();
timer.schedule(task2,10000);
timer.schedule(task1,100,3000);
}
}結(jié)果:

2.2 異?,F(xiàn)象
現(xiàn)象操作,在timetask2中,模擬一個(gè)除以0的算術(shù)異常。
強(qiáng)調(diào):在執(zhí)行任何一個(gè)任務(wù)的run方法時(shí),一旦run拋出了異常,Timer線程就會(huì)退出,從而所有定時(shí)任務(wù)都會(huì)被取消。如果希望各個(gè)定時(shí)任務(wù)互不干擾,一定要在run方法內(nèi)捕獲所有異常。
這里catch的異常為:integerrupteException

改成Exceptione 如圖

啟動(dòng)兩個(gè)timer

總結(jié)
1個(gè)timer沒(méi)有cancel掉,使用的一直是一個(gè)線程id;1個(gè)timer關(guān)閉后,再每次new后,使用的線程id都不相同。

在1個(gè)timer中,開(kāi)啟兩個(gè)timetask;這個(gè)兩個(gè)timertask串行執(zhí)行,單線程;使用的線程id是相同的。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
全面解析JPA?倉(cāng)庫(kù)repository中的findAll()方法
這篇文章主要介紹了全面解析JPA?倉(cāng)庫(kù)repository中的findAll()方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
Java中synchronized和ReentrantLock的區(qū)別對(duì)比
這篇文章主要介紹了Java中synchronized和ReentrantLock的區(qū)別對(duì)比,synchronized和ReentrantLock是Java中兩種主要的線程同步機(jī)制,它們都能保證線程安全,但在實(shí)現(xiàn)和功能上有明顯區(qū)別,需要的朋友可以參考下本篇介紹2026-01-01
kafka-console-consumer.sh使用2次grep管道無(wú)法提取消息的解決
這篇文章主要介紹了kafka-console-consumer.sh使用2次grep管道無(wú)法提取消息的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
spring cloud中啟動(dòng)Eureka Server的方法
本篇文章主要介紹了spring cloud中啟動(dòng)Eureka Server的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Java 自定義Spring框架與Spring IoC相關(guān)接口分析
Spring框架是由于軟件開(kāi)發(fā)的復(fù)雜性而創(chuàng)建的。Spring使用的是基本的JavaBean來(lái)完成以前只可能由EJB完成的事情。然而,Spring的用途不僅僅限于服務(wù)器端的開(kāi)發(fā)2021-10-10
spring-data-redis連接操作redis的實(shí)現(xiàn)
spring-data-redis則是對(duì)Jedis進(jìn)行了高度封裝,使用起來(lái)非常方便。本文主要介紹了spring-data-redis連接操作redis的實(shí)現(xiàn),感興趣的可以了解一下2021-07-07
Java模擬單鏈表和雙端鏈表數(shù)據(jù)結(jié)構(gòu)的實(shí)例講解
這篇文章主要介紹了Java模擬單鏈表和雙端鏈表數(shù)據(jù)結(jié)構(gòu)的實(shí)例,注意這里的雙端鏈表不是雙向鏈表,是在單鏈表的基礎(chǔ)上保存有對(duì)最后一個(gè)鏈接點(diǎn)的引用,需要的朋友可以參考下2016-04-04
如何使用IDEA查看java文件編譯后的字節(jié)碼內(nèi)容
這篇文章主要介紹了如何使用IDEA查看java文件編譯后的字節(jié)碼內(nèi)容,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Java中的CountDownLatch簡(jiǎn)單理解
這篇文章主要介紹了Java中的CountDownLatch簡(jiǎn)單理解,CountDownLatch是一個(gè)同步工具類(lèi),用來(lái)攜調(diào)多個(gè)線程之間的同步,它是是使用一個(gè)計(jì)數(shù)器進(jìn)行實(shí)現(xiàn)的,計(jì)數(shù)器初始值為線程數(shù)量,需要的朋友可以參考下2024-01-01

