定时器Timer与TimerTask的使用

article/2025/8/30 10:18:03

一:简介

在JDK类库中Timer主要负责计划任务的功能,也就是在指定时间执行某一任务,执行时候会在主线程之外起一个单独的线程执行指定的任务。该类主要是设置任务计划,但封装的类是TimerTask类。
TimerTask是一个实现了Runnable接口的抽象类,代表一个可被执行的任务,执行任务的代码要放在其子类中(TimerTask是抽象类)。

二:Timer整体类图

在这里插入图片描述

TimerTask类:主要为定时任务的具体内容。
Timer类中含有3个类:Timer、TimerThread、TaskQueue。
Timer类主要是设置定时任务,配置用户期望的任务执行时间、执行次数、执行内容
TimerThread类为Thread的扩展类,会一直从TaskQueue中获取下标为1的TimerTask进行执行。并根据该TimerTask是否需要重复执行来决定是否放回到TaskQueue中。
TaskQueue中存放一些列将要执行的TimerTask,以数组的形式存放,下标约小(注:下标为0不处理,即使用的最小下标为1),则表明优先级越高。
public class Timer {//默认给线程命名:"Timer-" + serialNumber()public Timer() {this("Timer-" + serialNumber());}//指定Timer的名字public Timer(String name) {thread.setName(name);thread.start();}//isDaemon:是否为守护线程public Timer(boolean isDaemon) {this("Timer-" + serialNumber(), isDaemon);}//给定线程名字,守护线程与否public Timer(String name, boolean isDaemon) {thread.setName(name);//setDaemon是指定线程是否为守护线程,true是守护线程,当主线程退出,      守护线程退出thread.setDaemon(isDaemon);thread.start();}    
}//TimerThread类 继承Thread
class TimerThread extends Thread{private void mainLoop() {......//每次执行下标为1的TimerTasktask = queue.getMin();......}
}//TaskQueue 类
class TaskQueue {//TaskQueue 中存储TimerTaskprivate TimerTask[] queue = new TimerTask[128];//返回数组中下标1的TimerTaskTimerTask getMin() {return queue[1];}
}

三:Timer常用方法

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

1.task是定时任务,time是task任务执行时间.如果time时间早于当前则立即执行,否则在time时间执行。
2.task只执行一次,且执行完Timer线程任务不结束,因为Timer不是守护线程,Timer timer = new Timer(true);
是指定Timer 为守护线程,当task执行结束后,Timer 线程会立即结束。
3.Timer 可以执行多个定时任务,TimerTask 将会按照队列的方式一个一个被执行,如果前面的任务耗时长,后面的任务执行时间将会相应的延后。
public class TimerDemo {//指定Timer为守护线程,run方法结束Timer线程会结束。private static Timer timer = new Timer(true);//TimerTask 具体的定时任务static public class MyTask extends TimerTask {@Overridepublic void run() {System.out.println("已运行,时间为:" + new Date());}}public static void main(String[] args) {//创建定时任务MyTask myTask = new MyTask();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//早于当前时间,定时任务会立即执行String dateString = "2020-06-01 09:56:00";try {Date taskDate = sdf.parse(dateString);//启动定时任务timer.schedule(myTask,taskDate);} catch (Exception e) {e.printStackTrace();}}
}
已运行,时间为:Wed Jul 01 14:48:06 CST 2020

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

TimerTask任务在指定 firstTime任务之后,周期性每隔period时间,无限期循环的执行某一任务。

3.TimerTask 类boolean cancel()方法

TimerTask 类boolean cancel()方法,是将自身任务从任务队列中移除。

public class TimerDemo {private static Timer timer = new Timer();static public class MyTaskA extends TimerTask {@Overridepublic void run() {//只输出一次,MyTaskA 任务将会移除System.out.println("MyTaskA已运行,时间为:" + new Date());//执行TimerTask的cancel方法,将自身任务从队列中移除this.cancel();}}static public class MyTaskB extends TimerTask {@Overridepublic void run() {//移除MyTaskA任务,MyTaskB 任务不受影响System.out.println("MyTaskB已运行,时间为:" + 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();}}
}
MyTaskA已运行,时间为:Wed Jul 01 15:24:47 CST 2020
MyTaskB已运行,时间为:Wed Jul 01 15:24:47 CST 2020
MyTaskB已运行,时间为:Wed Jul 01 15:24:49 CST 2020
MyTaskB已运行,时间为:Wed Jul 01 15:24:51 CST 2020
MyTaskB已运行,时间为:Wed Jul 01 15:24:53 CST 2020
MyTaskB已运行,时间为:Wed Jul 01 15:24:55 CST 2020
MyTaskB已运行,时间为:Wed Jul 01 15:24:57 CST 2020
MyTaskB已运行,时间为:Wed Jul 01 15:24:59 CST 2020

4.Timer 类void cancel()方法

Timer 类void cancel()方法与TimerTask 类boolean cancel()方法将自身任务从任务队列中移除不同,它是将所有的任务都从队列中移除。

public class TimerDemo {private static Timer timer = new Timer();static public class MyTaskA extends TimerTask {@Overridepublic void run() {System.out.println("MyTaskA已运行,时间为:" + new Date());//执行Timer类的cancel方法,将Timer中所有任务从队列中移除timer.cancel();}}static public class MyTaskB extends TimerTask {@Overridepublic void run() {//MyTaskB也会被移除,因为MyTaskA与MyTaskB是队列执行,先执行MyTaskA再执行MyTaskB//MyTaskA中走了timer.cancel(),所以MyTaskB不会执行System.out.println("MyTaskB已运行,时间为:" + 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();}}
}
MyTaskA已运行,时间为: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.}}

执行cancel需要抢占queue锁,如果抢不到,则TimerTask 任务会继续执行。

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

该方法以schedule(TimerTask task, long delay)方法的执行时间为基准,在此时间上延迟指定的毫秒数delay后执行一次TimerTask 任务。

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

该方法以schedule(TimerTask task, long delay, long period)方法的执行时间为基准,在此时间上延迟指定的毫秒数delay后,执行TimerTask 任务,之后间隔period毫秒无限循环执行TimerTask 任务。

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

TimerTask任务在指定 firstTime任务之后,周期性每隔period时间,无限期循环的执行某一任务。

四:重点:scheduleAtFixedRate(TimerTask task, Date firstTime, long period)与 schedule(TimerTask task, Date firstTime, long period)方法区别

1.相同点:两个方法都是按照顺序执行,无线程安全问题
2.任务不延时相同点:如果任务执行时间小于任务时间间隔,则第二次任务的开始时间是任务开始时间+period
3.任务延时相同点:如果任务执行时间大于任务时间间隔,导致第二次任务开始时候,上一个任务还未结束,则第二次任务的开始时间是在第一次任务结束时候立即执行。

scheduleAtFixedRate方法与schedule方法的追赶性问题

scheduleAtFixedRate方法具有追赶性!!!!如果计划执行时间早于当前时间,执行scheduleAtFixedRate方法后立即执行定时任务,根据任务间隔时间与当前时间减去计划执行时间,补上之前少执行的任务。
schedule方法不具有追赶性。!!!!

public class TimerDemo {private static Timer timer = new Timer();static public class MyTaskA extends TimerTask {@Overridepublic void run() {System.out.println("MyTaskA已运行,时间为:" + new Date());try {//任务执行时间是1sThread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("MyTaskA已结束,时间为:" + 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执行一次任务timer.scheduleAtFixedRate(myTaskA,taskDate,3000);} catch (Exception e) {e.printStackTrace();}}
}
MyTaskA已运行,时间为:Thu Jul 02 14:34:38 CST 2020
MyTaskA已结束,时间为:Thu Jul 02 14:34:39 CST 2020
MyTaskA已运行,时间为:Thu Jul 02 14:34:39 CST 2020
MyTaskA已结束,时间为:Thu Jul 02 14:34:40 CST 2020
MyTaskA已运行,时间为:Thu Jul 02 14:34:40 CST 2020
MyTaskA已结束,时间为:Thu Jul 02 14:34:41 CST 2020
MyTaskA已运行,时间为:Thu Jul 02 14:34:41 CST 2020
MyTaskA已结束,时间为:Thu Jul 02 14:34:42 CST 2020
MyTaskA已运行,时间为:Thu Jul 02 14:34:42 CST 2020
MyTaskA已结束,时间为:Thu Jul 02 14:34:43 CST 2020
MyTaskA已运行,时间为:Thu Jul 02 14:34:43 CST 2020
MyTaskA已结束,时间为:Thu Jul 02 14:34:44 CST 2020
MyTaskA已运行,时间为:Thu Jul 02 14:34:44 CST 2020
MyTaskA已结束,时间为:Thu Jul 02 14:34:45 CST 2020
MyTaskA已运行,时间为:Thu Jul 02 14:34:45 CST 2020
MyTaskA已结束,时间为:Thu Jul 02 14:34:46 CST 2020
MyTaskA已运行,时间为:Thu Jul 02 14:34:46 CST 2020

由上述执行结果可知,在Thu Jul 02 14:34:38 CST 2020启动定时任务后,没有间隔3s再执行下一次任务,而是任务结束就立即执行,这是因为任务计划执行时间早于当前时间,需要将这期间没有执行的任务补上。

五: 总结

java中可以使用定时任务的功能,针对不同的定时任务可以根据不同的API进行处理,从本质来说改技术仍然属于多线程,基于多线程实现,不管用再多的框架实现定时器功能,请不要忘了这事java基础,框架实现的基础。


http://chatgpt.dhexx.cn/article/CkgY9BdF.shtml

相关文章

Java的定时器Timer和定时任务TimerTask应用以及原理简析

记录:272 场景:Java JDK自带的定时器Timer和定时任务TimerTask应用以及原理简析。在JDK工具包:java.util中可以找到源码,即java.util.Timer和java.util.TimerTask。TimerTask实现Runnable接口的run方法。Timer的属性TimerThread …

原码、补码、反码的转换

1.原码 (1)一个正数,他的原码就是它对应的二进制数字。 (2)一个负数,按照绝对值大小转换成的二进制数,然后最高位补1,就是负数的原码。 2.反码 (1)正数的反…

原码、补码、反码的关系

一. 机器数和真值 在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念. 1、机器数 一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1. 比如,十进制中的数 3 &…

原码,反码,补码,阶码,移码

本文转载自本站大佬“不去上课”,原文链接https://blog.csdn.net/ruidianbaihuo/article/details/87875178 原码,反码,补码,阶码,移码是什么?有什么区别(讨论机器数的表示) 本文内容参考自王达老师的《深入理解计算机…

原码、反码、补码之间的转换和简单运算

一、正整数的原码、反码、补码完全一样,即符号位固定为0,数值位相同 二、负整数的符号位固定为1,由原码变为补码时,规则如下: 1、原码符号位1不变,整数的每一位二进制数位求反,得到反码 2、反码…

原码,反码,补码的概念

计算机里都是以补码的形式存储数据,电脑只能识别二进制的0和1, 一个字节(8位)为例 原码 :最高位符号位,0代表正数,1代表负数,非符号位为该数字绝对值的二进制。 反码:正…

C语言——原码, 反码, 补码 详解

目录 一. 机器数和真值 1、机器数 2、真值 二. 原码, 反码, 补码的基础概念和计算方法. 1. 原码 2. 反码 3. 补码 三. 为何要使用原码, 反码和补码 四 原码, 反码, 补码 再深入 同余的概念 负数取模 开始证明 一. 机器数和真值 在学习原码, 反码和补码之前, 需要先…

原码、反码、补码、移码的概念及转换

目录 前言 1.原码 2.反码 3.补码 4.移码 前言 学习完数的小数点表示,下一个需要解决的问题就是数的机器码表示问题。 在计算机中对数据进行运算操作时,符号位应该如何表示?是否也同数值位一道参加运算操作呢?如果参加&…

mt7620芯片处理器核心资料

MT7620产品系统整合了2T2R 802.11n Wi-Fi 收发器、580MHz MIPS 24KEc™ 中央处理器 (CPU)、5 端口高速以太网络端口物理层 (Ethernet PHY)、HNAT、存储器加速器、USB2.0 主机/设备,以及多种慢速输入输出 (U客论坛)。MT7620A 支持 PCIe、RGMII,适用于 AC7…

mt7620参考设计原理图,mt7620芯片资料,mt7620处理器资料

mt7620参考设计原理图,芯片资料,处理器资料 核心资料 芯片处理器资料 设计注意事项 处理器大全 音频语音设计资料文档(U客论坛) MT7620产品系统整合了2T2R 802.11n Wi-Fi 收发器、580MHz MIPS 24KEc™ 中央处理器 (CPU)、5 端口高速以太网络端口物理层 (Ethernet PHY)、HNAT…

MT7682参考手册,MT7682芯片资料介绍

MT7682 Reference Manual 2.总线体系结构与内存映射 MediaTek MT7682采用32位多AHB矩阵,为物联网和可穿戴设备提供低功耗、快速、灵活的数据操作.表2.1-1显示了总线主机之间的互连(Cortex-M4,四个spi主站,spi从机,调试系统&#…

MT7628 openwrt学习(1)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、拿到板子之后干的事情二、openwrt编译文件下载tftp中的坑 最后是SSH和简单的编译 前言 主要是用来记录我的MT7628踩坑经历,所有东西都是开源的…

mt7621芯片更换ram

最近公司设备的内存占用率过高,经常性的导致设备挂掉,于是准备换一个ram。 解决方案: 在openwrt目录下,进入target/linux/ramips/dts目录,找到设备使用的CPU型号对应的dts文件,然后修改其中内容。将memory的…

MT7621处理器资料解析,MT7621数据表

MT7621处理器资料解析,MT7621数据表 MT7621 Wi-Fi 系统单芯片包含功能强大的 880 MHz MIPS 1004KEc™ 双核心中心处理器 (CPU)、5 端口 Gigabit 以太网络交换器,以及RGMII、PCIe、USB、SD-XC 等众多连接选项。这款全新系统单芯片亦随附我们经现场验证的硬件支持,涵盖网络地…

MT6261处理器参数介绍,MT6261芯片资料

MT6261处理器: MT6261是一种基于低功耗CMOS工艺的集成前沿电源管理单元、模拟基带和无线电电路的单片芯片。 MT6261是一种功能丰富、功能非常强大的用于高端GSM/GPRS能力的单芯片解决方案。基于32位ARM7EJ-S TM RISC处理器,MT6261的卓越处理能力TH高带…

MT8167处理器型号对比,MT8167芯片资料介绍

MT8167平台有两个版本,分别是MT8167A和MT8167B。两者之间最大的、唯一的区别在于MT8167A提供略高的处理和图形性能规格,最大的区别是支持60pps的1080p视频解码(MT8167B的30fps以上)和全高清支持(19201200) …

mt7682芯片处理器详细资料介绍

MTK MT7682S是基于一个高度集成的芯片组,包括一个微控制器单元(MCU)、一个低功耗的1x11n单波段Wi-Fi子系统和一个电源管理单元(PMU)。单片机是一个带有浮点单元的ARM Cortex-M4处理器,与1MB的闪存集成在一起。 Wi-Fi子系统包含802.11b/g/n无线电、基带和…

MT7621A的首板终于收到了

经过一个近一个月的生产加工,MT7621A的硬件终天收到了。 先上两个图: 正面 刚拿到电路板,测试电源时竞然发现1.1VD对地短路。(一想这个可完了,刚做的电路板就短路,一定死定了) 通过认真仔细的分…

MT7628 wifi模块,MTK路由器芯片介绍

MT7628处理器: MT7628nn/mt7628an 系列产品是新一代2T2R 802.11n Wi-Fi AP / 路由器 (系统单芯片)。 MT7628可提升射频效能表现、减低功耗,并将整体物料清单 (BOM) 成本优化,令它成为性价比最出众的 2x2 11n 解决方案。MT7628产品家族整合了…

MT7621路由器芯片/处理器参数介绍

MT7621路由器芯片包括一个880 MHz MIPS 1004Kc™CPU双核,一个5端口10/100/1000交换机/PHY和一个RGMII。嵌入式高性能cpu可以很容易地处理高级应用程序。如路由、安全和VoIP等。MT7621还包括支持多种应用程序的接口选择,例如用于访问外部存储的USB端口。 …