当前位置: 首页 > news >正文

java.util.Timer简介以及简单使用示例

一、简介

定时器(Timer)是一个工具类,用于安排任务(java.util.TimerTask)在指定时间后执行或以指定的时间间隔重复执行。它可以用于执行定时任务、定时调度和时间延迟等操作。

定时器(Timer)可以应用于许多场景,比如:

调度任务(固定速率):当你需要按照预定时间执行任务时,可以使用定时器。例如,每天凌晨执行数据备份、定时生成报表、定时发送通知等。即scheduleAtFixedRate的2个重载方法。

超时处理(固定延迟):当你需要处理某个操作的超时情况时,可以使用定时器。例如,设置一个操作的超时时间,如果在规定时间内未完成,则执行相应的超时处理逻辑。即schedule的4个重载方法。

Java中的定时器:java.util.Timer,它的常用方法:

Java 8 中文版 - 在线API手册 - 码工具

Modifier and Type

Method and Description

参数说明

void

cancel()

终止此计时器,丢弃任何当前计划的任务。

/

int

purge()

从该计时器的任务队列中删除所有取消的任务。

/

void

schedule(TimerTask task, Date time)

在指定的时间安排指定的任务执行。如果此时间已过去,则安排立即执行该任务

task:要调度的任务

time:执行任务的时间

void

schedule(TimerTask task, Date firstTime, long period)

从指定 的时间开始 ,对指定的任务执行重复的 固定延迟执行 。

task:要调度的任务

firstTime:第一次执行任务的时间

period:连续任务以毫秒为单位的时间间隔

void

schedule(TimerTask task, long delay)

在指定的延迟之后安排指定的任务执行。

task:要调度的任务

delay:在执行任务之前,以毫秒为单位进行延迟的时间

void

schedule(TimerTask task, long delay, long period)

在指定 的延迟之后开始 ,重新执行 固定延迟执行的指定任务。

task:要调度的任务

delay:在执行任务之前,以毫秒为单位进行延迟的时间

period:连续任务以毫秒为单位的时间间隔

void

scheduleAtFixedRate(TimerTask task, Date firstTime, long period)

从指定的时间 开始 ,对指定的任务执行重复的 固定速率执行 。

task:要调度的任务

firstTime:第一次执行任务的时间

period:连续任务以毫秒为单位的时间间隔

void

scheduleAtFixedRate(TimerTask task, long delay, long period)

在指定的延迟之后 开始 ,重新执行 固定速率的指定任务。

task:要调度的任务

delay:在执行任务之前,以毫秒为单位进行延迟的时间

period:连续任务以毫秒为单位的时间间隔

二、schedule和scheduleAtFixedRate方法的区别

这两个方法都是任务调度方法,他们之间区别是,schedule会保证任务的间隔是按照定义的period参数严格执行的,如果某一次调度时间比较长,那么后面的时间会顺延,保证调度间隔都是period,而scheduleAtFixedRate是严格按照调度时间来的,如果某次调度时间太长了,那么会通过缩短间隔的方式保证下一次调度在预定时间执行。举个栗子:你每个3秒调度一次,那么正常就是0,3,6,9s这样的时间,如果第二次调度花了2s的时间,如果是schedule,就会变成0,3+2,8,11这样的时间,保证间隔,而scheduleAtFixedRate就会变成0,3+2,6,9,压缩间隔,保证调度时间。

三、定时器(Timer)使用步骤

我们要实现一个定时任务,只需要实现TimerTask的run方法即可。每一个任务都有下一次执行时间nextExecutionTime(毫秒),如果是周期性的任务,那么每次执行都会更新这个时间为下一次的执行时间,当nextExecutionTime小于当前时间时,都会执行它。

(1)第一步:创建一个Timer。

(2)第二步:创建一个TimerTask。

(3)第三步:使用Timer执行TimerTask。

其中第三步无疑是我们目前最关心的,也就是timer.schedule(myTask, 2000L, 1000L)。他的意思是myTask在两秒钟之后开始第一次执行,然后每隔一秒执行一次。这只是最基本的用法。就体现了Timer定时执行的流程。

示例1:超时处理(固定延迟)

在2秒后开始执行,只执行一次

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class TimeTest {public static void main(String[] args) {System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));Timer timer = new Timer();  // (1)第一步:创建一个Timer。timer.schedule(new TimerTask() {  // (2)第二步:创建一个TimerTask。(3)第三步:使用Timer执行TimerTask。@Overridepublic void run() {System.out.println("Timer is running");System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));}}, 2000);}
}

运行结果:

当前时间:2023-08-19 22-45-46:161

Timer is running

当前时间:2023-08-19 22-45-48:169

示例2:调度任务(固定速率)

执行周期性任务,只需要添加schedule的第三个参数period。

在2秒后开始执行,每隔1秒执行一次

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class TimeTest {public static void main(String[] args) {System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));Timer timer = new Timer(); // (1)第一步:创建一个Timer。timer.schedule(new TimerTask() { // (2)第二步:创建一个TimerTask。(3)第三步:使用Timer执行TimerTask。@Overridepublic void run() {System.out.println("Timer is running");System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));}}, 2000, 1000);}
}

运行结果:

当前时间:2023-08-19 22-48-10:190

Timer is running

当前时间:2023-08-19 22-48-12:200

Timer is running

当前时间:2023-08-19 22-48-13:203

Timer is running

当前时间:2023-08-19 22-48-14:216

示例32个Timer实例调度任务(固定速率)

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class TimeTest {public static void main(String[] args) {System.out.println("timer当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));Timer timer = new Timer(); // (1)第一步:创建一个Timer。timer.schedule(new TimerTask() { // (2)第二步:创建一个TimerTask。(3)第三步:使用Timer执行TimerTask。@Overridepublic void run() {System.out.println("Timer is running");System.out.println("timer当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));}}, 2000, 1000);System.out.println("timer2当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));Timer timer2 = new Timer(); // (1)第一步:创建一个Timer。timer2.schedule(new TimerTask() { // (2)第二步:创建一个TimerTask。(3)第三步:使用Timer执行TimerTask。@Overridepublic void run() {System.out.println("Timer2 is running");System.out.println("timer2当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));}}, 3000, 2000);}
}

运行结果:

timer当前时间:2023-08-20 00-08-06:746

timer2当前时间:2023-08-20 00-08-06:748

Timer is running

timer当前时间:2023-08-20 00-08-08:750

Timer is running

Timer2 is running

timer2当前时间:2023-08-20 00-08-09:755

timer当前时间:2023-08-20 00-08-09:755

Timer is running

timer当前时间:2023-08-20 00-08-10:769

Timer2 is running

timer2当前时间:2023-08-20 00-08-11:768

Timer is running

timer当前时间:2023-08-20 00-08-11:784

Timer is running

timer当前时间:2023-08-20 00-08-12:787

Timer2 is running

timer2当前时间:2023-08-20 00-08-13:770

四、Timer的缺陷

1、由于执行任务的线程只有一个,所以如果某个任务的执行时间过长,那么将破坏其他任务的定时精确性。如一个任务每1秒执行一次,而另一个任务执行一次需要5秒,那么如果是固定速率的任务,那么会在5秒这个任务执行完成后连续执行5次,而固定延迟的任务将丢失4次执行。

2、如果执行某个任务过程中抛出了异常,那么执行线程将会终止,导致Timer中的其他任务也不能再执行。

3、Timer使用的是绝对时间,即是某个时间点,所以它执行依赖系统的时间,如果系统时间修改了的话,将导致任务可能不会被执行。

五、更好的替代方法

由于Timer存在上面说的这些缺陷,在JDK1.5中,我们可以使用ScheduledThreadPoolExecutor来代替它,使用Executors.newScheduledThreadPool工厂方法或使用ScheduledThreadPoolExecutor的构造函数来创建定时任务,它是基于线程池的实现,不会存在Timer存在的上述问题,当线程数量为1时,它相当于Timer。

相关文章:

java.util.Timer简介以及简单使用示例

一、简介 定时器(Timer)是一个工具类,用于安排任务(java.util.TimerTask)在指定时间后执行或以指定的时间间隔重复执行。它可以用于执行定时任务、定时调度和时间延迟等操作。 定时器(Timer)可以…...

C语言笔试训练【第12天】

文章目录 1、请阅读以下程序,其运行结果是( )2、假设编译器规定 int 和 short 类型长度分别为32位和16位,若有下列C语言语句,则 y 的机器数为( )3、下列程序的输出结果是什么( &…...

外网连接局域网的几种方式?快解析内网穿透安全便利吗?

外网连接局域网是一项网络连接中的关键技术,它能够让远程用户通过互联网访问内部局域网中的资源和服务。外网连接局域网为企业提供了更大的灵活性和便捷性,但也需要严格的安全措施来防止未经授权的访问。 外网连接局域网的几种方式 在将外网连接到局域…...

基于互斥锁的生产者消费者模型

文章目录 生产者消费者 定义代码实现 / 思路完整代码执行逻辑 / 思路 局部具体分析model.ccfunc(消费者线程) 执行结果 生产者消费者 定义 生产者消费者模型 是一种常用的 并发编程模型 ,用于解决多线程或多进程环境下的协作问题。该模型包含…...

USB隔离器电路分析,SA8338矽塔sytatek电机驱动,源特科技VPS8701,开关电源,电源 大师

一、 USB隔离器电路分析 进行usb隔离可以使用USB隔离模块 ADUM3160 ADUM4160 注意:B0505S 最大带载0.16A,副边需要带载能力需要改变方案 比如移动硬盘至少需要0.5A 用充电宝、18650、设计5V1A输出电源 二、 1A隔离电压方案...

TPC-DS 测试是否支持 Glue Data Catalog?

在上一篇文章《在Hive/Spark上执行TPC-DS基准测试 (PARQUET格式)》中,我们详细介绍了具体的操作方法,当时的集群使用的是Hive Metastore,所有操作均可成功执行。当集群启用 Glue Data Catalog 时,在执行add_constraints.sql时会报错: Optimizing table date_dim (1/24).…...

网络编程(8.14)TCP并发服务器模型

作业: 1. 多线程中的newfd,能否修改成全局,不行,为什么? 2. 多线程中分支线程的newfd能否不另存,直接用指针间接访问主线程中的newfd,不行,为什么? 多线程并发服务器模型原代码&…...

认识负载均衡||WEBSHELL

目录 一、负载均衡 1.nginx负载均衡算法 2.nginx反向代理-负载均衡 二、webshell 1.构造不含数字和字母的webshell 2.如何绕过 一、负载均衡 1.nginx负载均衡算法 (1)轮询(默认)每个请求按时间顺序逐一分配到不同的后端服务&…...

Chapter 15: Object-Oriented Programming | Python for Everybody 讲义笔记_En

文章目录 Python for Everybody课程简介Object-oriented programmingManaging larger programsGetting startedUsing objectsStarting with programsSubdividing a problemOur first Python objectClasses as typesObject lifecycleMultiple instancesInheritanceSummaryGlossa…...

模板编程-成员特化

成员特化:类模板特化除了可以对整个类进行特化外,可以只针对某部分成员函数进行特化 全类特化和成员特化都属于全局特化 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstring>template<typename T> class CMath { public:CMath(const…...

信安通用基础知识

文章目录 密码学经典误区PGP优良保密协议信安经典其它安全手段XSS与CSRF cross site request forgeryCSRF的利用逻辑CSRF示例CSRF防范检查Referer字段添加校验token XSS cross site scripting common weakness enumeration常见密码api误用&#xff08;摘自毕设参考文献&#xf…...

网上购物系统的设计与实现/在线商城/基于spring boot的电商平台/基于Java的商品销售系统

摘 要 本毕业设计的内容是设计并且实现一个基于Springboot的网上购物系统。它是在Windows下&#xff0c;以MYSQL为数据库开发平台&#xff0c;Tomcat网络信息服务作为应用服务器。网上购物系统的功能已基本实现&#xff0c;主要包括用户管理、数码分类管理、数码产品管理、服…...

uniapp项目-配置store文件夹

1.创建store.js 说明&#xff1a;创建一个新的 Vuex Store 实例&#xff0c;配置 Store 中的模块。 import Vue from vue; import Vuex from vuex; // 导入两个 Vuex 模块&#xff1a;moduleCart 和 moduleUser import moduleCart from /store/cart.js; import moduleUser fr…...

element表格多选实现

表格实现多选 实现表格多选很简单&#xff0c;只需要在表格里加上一列即可&#xff0c;加完之后就会在表格里出现一列白色的四方块按钮&#xff0c;可以多选&#xff0c;也可以单选 <el-table-columntype"selection"width"55"align"center"&…...

宠物智能自动喂食器方案设计

据相关数据表明&#xff0c;2019年全国城镇宠物犬猫数量达到9915万只&#xff0c;增幅达到8.4%&#xff0c;消费市场规模达2024亿元&#xff0c;比2018年增长18.5%&#xff0c;整体呈现持续大幅增长的态势。而养宠人群的主力&#xff0c;为25岁至38岁年轻人&#xff0c;都市白领…...

学习笔记230818---对于promise失败状态处理的重要性

问题描述&#xff1a; 在项目中经常会出现如上的问题&#xff0c;这是因为&#xff0c;用promise封装的接口或第三方组件方法&#xff0c;如果只对成功的状态做处理&#xff0c;就会造成页面出错&#xff0c;报error。 解决方法 then()的末尾加上.catch(()>{})对失败的状态…...

【Redis】什么是缓存击穿,如何预防缓存击穿?

【Redis】什么是缓存击穿&#xff0c;如何预防缓存击穿&#xff1f; 缓存击穿是指一个 Key 非常热点&#xff0c;大并发集中对这一个点进行访问&#xff0c;当这个Key 在失效的瞬间&#xff0c;持续的大并发就会穿破缓存&#xff0c;直接请求数据库。缓存击穿和缓存雪崩的区别…...

Android 13.0 强制app横屏显示

1.概述 在13.0产品定制化开发中,对于处理屏幕旋转方向,首先有kernel底层处理,从底层驱动gsensor 中获取数据,从而判断屏幕方向的,然后事件上报后 最后由WMS就是WindowManagerService 来处理旋转的相关事件 2.强制app横屏显示的核心类 /framework/base/services/java/com…...

平方数之和(力扣)双指针 JAVA

给定一个非负整数 c &#xff0c;你要判断是否存在两个整数 a 和 b&#xff0c;使得 a&#xff3e;2 b&#xff3e;2 c 。 示例 1&#xff1a; 输入&#xff1a;c 5 输出&#xff1a;true 解释&#xff1a;1 * 1 2 * 2 5 示例 2&#xff1a; 输入&#xff1a;c 3 输出&am…...

深入浅出Pytorch函数——torch.nn.init.sparse_

分类目录&#xff1a;《深入浅出Pytorch函数》总目录 相关文章&#xff1a; 深入浅出Pytorch函数——torch.nn.init.calculate_gain 深入浅出Pytorch函数——torch.nn.init.uniform_ 深入浅出Pytorch函数——torch.nn.init.normal_ 深入浅出Pytorch函数——torch.nn.init.c…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

性能优化中,多面体模型基本原理

1&#xff09;多面体编译技术是一种基于多面体模型的程序分析和优化技术&#xff0c;它将程序 中的语句实例、访问关系、依赖关系和调度等信息映射到多维空间中的几何对 象&#xff0c;通过对这些几何对象进行几何操作和线性代数计算来进行程序的分析和优 化。 其中&#xff0…...

TMC2226超静音步进电机驱动控制模块

目前已经使用TMC2226量产超过20K,发现在静音方面做的还是很不错。 一、TMC2226管脚定义说明 二、原理图及下载地址 一、TMC2226管脚定义说明 引脚编号类型功能OB11电机线圈 B 输出 1BRB2线圈 B 的检测电阻连接端。将检测电阻靠近该引脚连接到地。使用内部检测电阻时,将此引…...