Java定时任务Timer、TimerTask与ScheduledThreadPoolExecutor详解

article/2025/8/30 9:48:54

目录

一、Timer和TimerTask

1、快速入门

2、schedule与scheduleAtFixedRate使用方法

3、schedule与scheduleAtFixedRate区别

4、终止Timer线程

5、Timer线程的缺点

二、ScheduledThreadPoolExecutor

1、构造方法   

2、调度方法

3、与Timer相比,优点


   定时任务就是在指定时间执行程序,或周期性执行计划任务。Java中实现定时任务的方法有很多,本文从从JDK自带的一些方法来实现定时任务的需求。

一、Timer和TimerTask

   TimerTimerTask可以作为线程实现的常见方式JDK1.5之后定时任务推荐使用ScheduledThreadPoolExecutor

1、快速入门

   Timer运行在后台,可以执行任务一次,或定期执行任务。TimerTask类继承了Runnable接口,因此具备多线程的能力。一个Timer可以调度任意多个TimerTask,所有任务都存储在一个队列中顺序执行,如果需要多个TimerTask并发执行,则需要创建两个多个Timer

  一个简单使用Timer的例子如下:

import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class TimerTest { //被执行的任务必须继承TimerTask,并且实现run方法static class MyTimerTask1 extends TimerTask { public void run() { System.out.println("爆炸!!!"); } }    public static void main(String[] args) throws ParseException { Timer timer = new Timer(); //1、设定两秒后执行任务//timer.scheduleAtFixedRate(new MyTimerTask1(), 2000,1000);//2、设定任务在执行时间执行,本例设定时间13:57:00SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); Date time = dateFormatter.parse("2023/02/11 14:40:00"); timer.schedule(new MyTimerTask1(), time);} } 

2schedulescheduleAtFixedRate使用方法

   schedule(TimerTask task, long delay, long period)   --指定任务执行延迟时间

   schedule(TimerTask task, Date time, long period)    --指定任务执行时刻

   scheduleAtFixedRate(TimerTask task, long delay, long period)

   scheduleAtFixedRate(TimerTask task, Date firstTime, long period)

3schedulescheduleAtFixedRate区别

   1) schedule

    注重任务执行的平滑度,也就是说任务队列中某个任务执行延迟了某个时间,接下来的其余任务都会延迟相同时间,来最大限度的保证任务与任务之间的时间间隔的完整性;

    当程序指定开始时刻(Date time)小于当前系统时刻时,会立即执行一次任务,之后的任务开始执行时间以当前时刻为标准,结合时间间隔计算得到;

   例:计划任务程序指定从2023/02/11 18:00:00开始每隔3分钟执行一次任务。如果该程序在18:00:00之前运行,则计划任务程序分别会在18:00:00、18:03:00、18:06:00...等时间点执行任务;如果该程序在18:00:00之后运行,如在18:07:00时刻开始运行程序,计划任务程序判断指定开始执行时刻18:00:00小于当前系统时刻,于是立即执行一次任务,接下来任务时间时刻分别为18:10:00、18:13:00、18:16:00...;而当使用scheduleAtFixedRate执行计划任务时,无论计划任务程序在什么时候运行,所有任务执行的次数都按照原计划,不会因为程序执行时刻的早晚而改变。而当程序运行时刻比计划任务计划首次执行时间晚时,如同样在18:07:00时刻开始执行程序,则计划任务程序会立马计算程序执行时刻晚于指定时刻,会立即执行(18:07:00-18:00:00)/3+1=3次任务(代表18:00:00、18:03:00和18:06:00三个时刻执行的任务),接下来任务执行时刻是18:09:00、18:12:00等。


import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class TimerRateFix {public static void main(String[] args) throws ParseException {final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); Date startDate = dateFormatter.parse("2023/02/11 18:00:00"); Timer timer = new Timer(); timer.schedule(new TimerTask(){ public void run() { System.out.println("执行任务,当前时刻:" + dateFormatter.format(new Date())); } },startDate,3*60*1000); }}

    当执行任务的时间间隔t1大于周期间隔t2时,下一次任务执行时间点相对于上一次任务实际执行完成的时间点,每个任务的执行时间会延后,第n个计划任务的实际执行时间比预计要延后(t1-t2)*n个时间单位。

   例:计划任务程序指定从2023/02/11 18:00:00开始每隔5秒执行一次任务,每次任务执行时间为6秒。当程序在18:00:00之前执行时,schedule分别会在18:00:00、18:00:06、18:00:12...等时间点执行计划任务,每隔时间点间隔6秒。原因是根据计划,第一个计划任务应会在18:00:00执行,第二个计划任务应会在18:00:05执行,而在18:00:05时间点,第一个任务才执行了5秒,还需要1秒才执行结束,因此第二个任务不能执行,于是等待1秒后在18:00:06时刻执行,之后每个任务均如此,均比原定执行时刻有延迟,每个任务时间间隔为6秒。当使用scheduleAtFixedRate执行计划任务时,第一个计划任务在18:00:00时刻执行,第二个会根据计划在18:00:05执行,第三个会在18:00:10执行,每个任务执行时间间隔为5秒,详细执行情况如下图所示

 图1 schedule与scheduleAtFixedRate任务执行区别

import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class TimerRateTest { public static void main(String[] args) throws ParseException { final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); Timer timer = new Timer(); Date time = dateFormatter.parse("2023/02/11 18:00:00");//假设程序在2023/02/11 18:00:00之前启动//1、使用scheduleAtFixedRate,每个计划任务执行时间点严格为18:00:00、18:00:05、18:00:10...,当任务执行时间大于时间间隔时可能会有并发情况//2、使用schedule,每个计划任务执行时间点根据上一个任务执行结束时间及时间间隔来计算//     当任务执行时间t1>时间间隔t2时,第N个计划任务执行时间点延迟为(t1-t2)*N,执行时间点为18:00:00+t2*(N-1)+(t1-t2)*N//    当任务执行时间t1<=时间间隔t2时,第N个计划任务执行时间点无延迟,执行时间为原计划timer.scheduleAtFixedRate(new TimerTask(){ public void run() { try { //每个计划任务执行时间为6秒Thread.sleep(6000); } catch (InterruptedException e) { e.printStackTrace(); }System.out.println("结束当前任务,当前时间:"+ dateFormatter.format(new Date())); } },time,5000);  //计划任务执行时间间隔为5秒} } 

   2) scheduleAtFixedRate:

    注重任务执行的频度,也就是说计划任务程序开始执行,每隔任务执行的时间点就已经确定,并不会因为某个任务的延迟而延迟执行其他任务,可以保证任务执行的时间效率;

    当程序指定开始时刻(Date firstTime)小于当前系统时刻时,会立即执行任务,执行次数为(当前系统时刻-指定开始时刻)/时间间隔,之后的任务开始执行时刻与当前系统时刻无关,仍按照程序指定开始时刻根据时间间隔计算得到;

    当执行任务的时间间隔t1大于周期间隔t2时,下一次任务执行时间点还是按照原定计划不变,加入阻塞队列,等待上一个任务完成,立即执行;只要满足周期就会加入阻塞队列

4、终止Timer线程

   1) 调用Timer.cancle()方法。可以在程序任何地方调用,甚至在TimerTask中的run方法中调用;

   2) 创建Timer时定义位daemon守护线程,使用new Timer(true)语句;

   3) 设置Timer对象为null,其会自动终止;

   4) 调用System.exit方法,整个程序终止。

5Timer线程的缺点

   1) Timer线程不会捕获异常,所以TimerTask抛出的未检查的异常会终止timer线程。如果Timer线程中存在多个计划任务,其中一个计划任务抛出未检查的异常,则会引起整个Timer线程结束,从而导致其他计划任务无法得到继续执行。  

   2) Timer线程时基于绝对时间(如:2023/02/14 16:06:00),因此计划任务对系统的时间的改变是敏感的。

   3) Timer是单线程,如果某个任务很耗时,可能会影响其他计划任务的执行。

   因此,JDK1.5以上建议使用ScheduledThreadPoolExecutor来代替Timer执行计划任务。   

二、ScheduledThreadPoolExecutor

  ScheduledThreadPoolExecutorJDK1.5以后推出的类,用于实现定时、重复执行的功能,官方文档解释要优于Timer

1、构造方法   

   1) ScheduledThreadPoolExecutor(int corePoolSize) 使用给定核心池大小创建一个新定定时线程池 

   2) ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactorythreadFactory) 使用给定的初始参数创建一个新对象,可提供线程创建工厂


private final static ScheduledThreadPoolExecutor schedual = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {private AtomicInteger atoInteger = new AtomicInteger(0);public Thread newThread(Runnable r) {Thread t = new Thread(r);t.setName("xxx-Thread "+ atoInteger.getAndIncrement());return t;}});

2、调度方法

   1) schedule(Callable callable, long delay, TimeUnit unit);  延迟delay时间后开始执行callable

   2) scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);  延迟initialDelay时间后开始执行command,并且按照period时间周期性重复调用,当任务执行时间大于间隔时间时,之后的任务都会延迟,此时与Timer中的scheduleAtFixedRate方法类似

   3) scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);  延迟initialDelay时间后开始执行command,并且按照period时间周期性重复调用,这里的间隔时间delay是等上一个任务完全执行完毕才开始计算

2 ScheduledThreadPoolExecutor.scheduleWithFixedDelayTimer.scheduleAtFixedRate任务执行区别

3、与Timer相比,优点

   1) ScheduledThreadPoolExecutor线程会捕获任务重的异常,即使多个计划任务中存在某几个计划任务为捕获异常的情况,也不会影响ScheduledThreadPoolExecutor总线程的工作,不会影响其他计划任务的继续执行。

   2) ScheduledThreadPoolExecutor是基于相对时间的,对系统时间的改变不敏感,但是如果执行某一绝对时间(如2023/02/14 17:13:06)执行任务(整秒 、整分执行任务),可能不好执行,此时可使用Timer

   3) ScheduledThreadPoolExecutor是线程池,如任务数过多或某些任务执行时间较长,可自动分配更多的线程来执行计划任务。

   总之,JDK1.5之后,计划任务建议使用ScheduledThreadPoolExecutor


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

相关文章

TimerTask

详解java定时任务 在我们编程过程中如果需要执行一些简单的定时任务&#xff0c;无须做复杂的控制&#xff0c;我们可以考虑使用JDK中的Timer定时任务来实现。下面LZ就其原理、实例以及Timer缺陷三个方面来解析java Timer定时器。 一、简介 在java中一个完整定时任务需要由Time…

Java Timer TimerTask示例

Java java.util.Timer是一个实用程序类&#xff0c;可用于调度将来某个时间执行的线程。Java Timer类可用于计划要一次运行的任务或定期运行的任务。 Java TimerTask java.util.TimerTask是一个实现Runnable接口的抽象类&#xff0c;我们需要扩展这个类来创建我们自己的Timer…

Timer+TimerTask实现数字时钟

成果展示 布局 布局主题背景颜色采用#000000&#xff08;纯黑色&#xff09;&#xff0c;各TextView字体颜色采用#FFFFFF(纯白色)。 使用五个TextView&#xff0c;分别实现小时&#xff1a;分钟&#xff0c;秒钟&#xff0c;am&#xff0c;pm&#xff0c;周日&#xff0c;具体…

Timer + TimerTask 实现数字时钟

任务&#xff1a; 自己完成的&#xff1a; 遇到的问题&#xff1a; 1.Android Studio 中 calendar设置系统时区无效的问题 14&#xff1a;50它显示为06&#xff1a;50&#xff0c;时间显示错误&#xff0c;这是因为时区不同。 在8.0以后设置时区&#xff0c;有所改动&#xf…

java定时器-Timer和TimerTask详解

1、例子入手 package pers.growing.test;import java.util.Timer; import java.util.TimerTask;public class Main {/*** 延迟100ms后&#xff0c;间隔1s打印出&#xff1a;hello world** param args* throws InterruptedException*/public static void main(String[] args) t…

定时器Timer与TimerTask的使用

一&#xff1a;简介 在JDK类库中Timer主要负责计划任务的功能&#xff0c;也就是在指定时间执行某一任务&#xff0c;执行时候会在主线程之外起一个单独的线程执行指定的任务。该类主要是设置任务计划&#xff0c;但封装的类是TimerTask类。 TimerTask是一个实现了Runnable接口…

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

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

原码、补码、反码的转换

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

原码、补码、反码的关系

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

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

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

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

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

原码,反码,补码的概念

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

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

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

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

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

mt7620芯片处理器核心资料

MT7620产品系统整合了2T2R 802.11n Wi-Fi 收发器、580MHz MIPS 24KEc™ 中央处理器 (CPU)、5 端口高速以太网络端口物理层 (Ethernet PHY)、HNAT、存储器加速器、USB2.0 主机/设备&#xff0c;以及多种慢速输入输出 (U客论坛)。MT7620A 支持 PCIe、RGMII&#xff0c;适用于 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矩阵&#xff0c;为物联网和可穿戴设备提供低功耗、快速、灵活的数据操作.表2.1-1显示了总线主机之间的互连(Cortex-M4&#xff0c;四个spi主站&#xff0c;spi从机&#xff0c;调试系统&#…

MT7628 openwrt学习(1)

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

mt7621芯片更换ram

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

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

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