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

Java多线程-----定时器(Timer)及其实现

目录

一.定时器简介:

二.定时器的构造方法与常见方法:

三.定时器的模拟实现:

思路分析:

代码实现:


在开发中,我们经常需要一些周期性的操作,例如每隔几分钟就进行某一项操作,这时候我们就需要去设置个定时器,Java中最方便,最高效的实现方式是用java.util.Timer工具类,在通过调度java.util.TimerTask任务来完成

一.定时器简介:

①.Timer是一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者是定期的重复执行,实际上是个线程,定时调度所拥有的TimerTask任务

②.TimerTask是一个抽象类,它的子类由Timer安排为一次执行或者重复执行的任务,实际上就是一个拥有run方法的类,需要定时执行的代码放到run方法体内.

二.定时器的构造方法与常见方法:

①.构造方法:

②.常用方法:

注意事项:

①.上述方法中TimerTask是一个抽象方法,其子类是一个可以被Timer执行的任务,要执行的代码放在run()方法体内实现

②.schedule()与scheduleAtFixedRate()的区别? 首先schedule(TimerTask task,Date time)与schedule(TimerTask task,long delay)都只是单次执行操作,并不存在多次调用任务的情况,所以没有提供scheduleAtFixedRate方法的调用方式。它们实现的功能都一样,那区别在哪里呢? (1)schedule()方法更注重保持间隔时间的稳定:保障每隔period时间可调用一次。

(2)scheduleAtFixedRate()方法更注重保持执行频率的稳定:保障多次调用的频率趋近于period    时间,如果某一次调用时间大于period,下一次就会尽量小于period,以保障频率接近于period。

.每一个Timer仅对应一个线程,而不是每调用一次schedule就创建一个线程

④.Timer是线程安全的

代码实例1:

import java.util.Timer;
import java.util.TimerTask;
public class Mian {public static void main(String[] args) throws InterruptedException {//创建定时器线程对象同时设置名字Timer timer = new Timer("定时器线程");//传入要执行的任务,同时设置等待的时间timer.schedule(new TimerTask() {@Overridepublic void run() {String current = Thread.currentThread().getName();System.out.println(current + " : 任务代码的执行区域~~~");}},2000);Thread.sleep(3000);System.out.println("执行结束");//结束定时器线程timer.cancel();}
}

运行结果:

代码实例2:

import java.util.Timer;
import java.util.TimerTask;
public class Mian2 {public static void main(String[] args) throws InterruptedException {//创建定时器线程对象同时设置名字Timer timer = new Timer("定时器线程");//传入要执行的任务,同时设置等待的时间timer.schedule(new TimerTask() {@Overridepublic void run() {String current = Thread.currentThread().getName();System.out.println(current + " : 任务代码的执行区域~~~");}},1000,2000);Thread.sleep(6000);//结束定时器线程timer.cancel();}
}

运行结果:

三.定时器的模拟实现:

在了解了什么是定时器和定时器的使用之后,那么定时器是如何实现的呢?这里我们通过模拟实现定时器,来进一步加深对定时器的理解。注:这里我们仅仅模拟实现Timer类不带参数的构造方法和等待delay时间后要执行的任务类,以及核心方法schedule。

思路分析:

Timer类通过schedule添加等待delay时间后执行的代码,此时的任务可能不止一个,我们需要一个容器来存放这些任务,同时,为了公平起见,我们让先到达指定时间的任务优先执行,很自然的我们可以想到用优先级队列来存储这些任务,队首元素就是最先执行的任务.

同时,我们也需要一个线程来扫描队首元素,判断队首元素是否是需要执行的任务

综上,我们自己模拟实现的定时器需要完成以下任务:

①.用一个优先级队列存放要执行的任务,队首元素是最先执行的任务

②.任务中带有时间属性,记录任务所要执行的时间

③.用一个线程来扫描队首元素,判断队首元素是否需要执行

④.这里出现多个线程同时操作共享数据的代码,我们要解决线程安全问题

代码实现:

import java.util.*;
class MyTimerTask implements Comparable<MyTimerTask>{//要执行的任务代码private Runnable runnable;//ms级别的时间戳private long time;public MyTimerTask(Runnable runnable,long delay){this.runnable = runnable;//计算要执行的相对时间:当前时间+等待时间this.time = System.currentTimeMillis() + delay;}public void run(){runnable.run();}public long getTime(){return time;}//重写compareTo比较方法,按照时间的从小到大排序@Overridepublic int compareTo(MyTimerTask o) {return (int)(this.time - o.time);}}
//模拟实现定时器
class MyTimer{private PriorityQueue<MyTimerTask> q = new PriorityQueue<>();//锁对象private static Object loker = new Object();//构造方法中启动线程,让线程进行判定与执行public MyTimer(){Thread t = new Thread(()->{try{while(true){//将操作共享数据的队列锁起来,一次只允许一个线程进行操作,避免线程安全问题synchronized (loker){if(q.isEmpty()){loker.wait();}MyTimerTask current = q.peek();//如果当前时间超过(>=) 设定的时间,此时需要执行任务if(System.currentTimeMillis() >= current.getTime()){current.run();//执行完成后,将任务从队列中删除q.poll();}else{//否则不执行任务loker.wait(current.getTime() - System.currentTimeMillis());}}}}catch (InterruptedException e) {e.printStackTrace();}});//开启线程t.start();}public void schedule(Runnable runnable,long delay){//将操作共享数据的队列锁起来,一次只允许一个线程进行操作,避免线程安全问题synchronized (loker){MyTimerTask myTimerTask = new MyTimerTask(runnable,delay);q.offer(myTimerTask);loker.notify();}}
}
//测试
public class Demo {public static void main(String[] args) {MyTimer myTimer = new MyTimer();myTimer.schedule(()->{System.out.println("hello Thread" + ",3000  " + Thread.currentThread().getName());},3000);myTimer.schedule(()->{System.out.println("hello Thread" + ",2000  " + Thread.currentThread().getName());},2000);myTimer.schedule(()->{System.out.println("hello Thread" + ",1000  " + Thread.currentThread().getName());},1000);}
}

运行结果:

参考资料:

Java定时器的使用(Timer简介)_51CTO博客_java定时器

资源--timer的使用 - 牛李 - 博客园 (cnblogs.com)

结语: 写博客不仅仅是为了分享学习经历,同时这也有利于我巩固知识点,总结该知识点,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进。同时也希望读者们不吝啬你们的点赞+收藏+关注,你们的鼓励是我创作的最大动力!

相关文章:

Java多线程-----定时器(Timer)及其实现

目录 一.定时器简介&#xff1a; 二.定时器的构造方法与常见方法&#xff1a; 三.定时器的模拟实现&#xff1a; 思路分析&#xff1a; 代码实现&#xff1a; 在开发中&#xff0c;我们经常需要一些周期性的操作&#xff0c;例如每隔几分钟就进行某一项操作&#xff0c;这…...

【Linux修行路】进度条小程序

目录 ⛳️推荐 一、预备知识 1.1 回车换行 1.2 缓冲区 二、倒计时 2.1 注意事项 三、进度条 3.1 源代码 3.2 代码分析 3.2 实际使用场景 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家…...

网络安全入门教程(非常详细)从零基础入门到精通,看完这一篇就够了。

学前感言: 1.这是一条坚持的道路,三分钟的热情可以放弃往下看了.2.多练多想,不要离开了教程什么都不会了.最好看完教程自己独立完成技术方面的开发.3.有时多google,baidu,我们往往都遇不到好心的大神,谁会无聊天天给你做解答.4.遇到实在搞不懂的,可以先放放,以后再来解决. 基…...

【探索Linux】P.44(数据链路层 —— 以太网的帧格式 | MAC地址 | MTU | ARP协议)

阅读导航 引言一、认识以太网二、以太网的帧格式三、MAC地址四、MTU五、ARP协议温馨提示 引言 在深入探讨了网络层的IP协议之后&#xff0c;本文将带领读者进一步深入网络的底层——数据链路层。我们将详细解析以太网的帧格式&#xff0c;这是数据链路层传输数据的基本单元&am…...

<数据集>航拍行人识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;7482张 标注数量(xml文件个数)&#xff1a;7482 标注数量(txt文件个数)&#xff1a;7482 标注类别数&#xff1a;1 标注类别名称&#xff1a;[people, pedestrian] 序号类别名称图片数框数1people5226385602pedes…...

在 Windows 10 系统上部署 Medusa

先决条件 在安装 Medusa 之前&#xff0c;你需要确保已经安装了以下工具&#xff1a; Node.js: Medusa 需要 Node.js v16 或更高版本。你可以从 Node.js 官网下载并安装。Git: Git 用于从 GitHub 获取 Medusa 的源代码。你可以从 Git 官网下载并安装。PostgreSQL: Medusa 使用…...

Linux进程 (冯诺依曼体结构 管理 PCB 进程状态 僵尸进程 孤儿进程 运行阻塞挂起状态 进程优先级)

文章目录 一.冯诺依曼体系结构冯诺依曼结构能干什么&#xff1f; 二.操作系统概念结构图(不完整)为什么要有操作系统&#xff1f; 尝试理解操作系统管理结构图(完整)总结&#xff1a; 三.进程进程是什么&#xff1f;PCB为什么要有PCB&#xff1f; Linux中的PCB进程的task_struc…...

《LlamaIndex 之美》-01-LLM、Prompt、Embedding基础入门

在基于数据构建任何 LLM 应用程序时&#xff0c;选择合适的大型语言模型 &#xff08;LLM&#xff09; 是您需要考虑的首要步骤之一。 LLM 是 LlamaIndex 的核心组成部分。它们可以作为独立模块使用&#xff0c;也可以插入到其他核心 LlamaIndex 模块&#xff08;索引、检索器…...

C++ 智能指针简单介绍及用法

C 智能指针简单介绍及用法 智能指针是 C11 引入的一个非常实用的特性&#xff0c;旨在自动管理动态分配的内存&#xff0c;避免内存泄漏和悬空指针问题。主要有三种类型的智能指针&#xff1a;std::unique_ptr、std::shared_ptr 和 std::weak_ptr。下面是对它们的详细介绍&…...

k8s笔记之创建Istio Gateway规则

创建Istio Gateway 背景如何创建Istio Gateway规则配置方式rewrite重写路径直接去除match&#xff0c;默认都转发到一个服务路由规则多种配置方式实践&#xff08;即开头的完整版&#xff09; 涉及的命令补充注意事项 背景 为什么需要使用到Istio Gateway&#xff1f;充当k8s服…...

NAND行业回归盈利:AI与云存储需求驱动

市场概览 根据Yole Group于2024年6月25日发布的市场报告&#xff0c;经过五个季度的亏损之后&#xff0c;NAND闪存行业在2024年第一季度&#xff08;1Q24&#xff09;实现了盈利回归。这一转变主要得益于企业级固态硬盘&#xff08;SSD&#xff09;领域的强劲需求增长&#xf…...

【限免】频控阵雷达:概念、原理与应用【附MATLAB代码】

​微信公众号&#xff1a;EW Frontier QQ交流群&#xff1a;949444104 主要内容 PDA、FDA MATLAB代码 %---------------------------------------- %功能:FDA和相控阵天线方向图 %版本:ver1.0 %时间:2017.11.1 %--------------------------------------- clear all; clc; disp…...

从0开始搭建vue + flask 旅游景点数据分析系统( 六):搭建后端flask框架

这一期开始开发header部分&#xff0c;预期实现两个目标&#xff1a; 创建 Flask 项目导入旅游数据后端实现旅游数据的查询 1 python 环境 & 开发环境 python 安装和pycharm安装需要去网上找包&#xff0c;建议python使用3.8 或者3.9版本 2 新建项目 我们新建一个文件…...

学习硬件测试04:触摸按键+PWM 驱动蜂鸣器+数码管(P62~P67、P71、P72)

一、触摸按键 1.1理论讲解 1.1.1实验现象 触摸按键 1 单击与长按&#xff0c;控制 LED1&#xff1b;触摸按键 2 单击与长按&#xff0c;控制 LED2;触摸按键 3 单击与长按&#xff0c;控制 LED3;触摸按键 4 单击与长按&#xff0c;控制继电器; 1.1.2硬件电路 是原理图上触摸…...

JS原型链

JS的原型链 文章目录 JS的原型链前言一、原型是什么&#xff1f;二、原型链总结 前言 在使用数组或对象中的方法时&#xff0c;你是不是会感觉很奇怪&#xff0c;为什么仅仅是创建了一个数组或是对象&#xff0c;就能够使用它提供的方法呢&#xff1f;JS是怎么做到的呢&#x…...

《Java初阶数据结构》----5.<二叉树的概念及使用>

前言 大家好&#xff0c;我目前在学习java。之前也学了一段时间&#xff0c;但是没有发布博客。时间过的真的很快。我会利用好这个暑假&#xff0c;来复习之前学过的内容&#xff0c;并整理好之前写过的博客进行发布。如果博客中有错误或者没有读懂的地方。热烈欢迎大家在评论区…...

git查看记录详解

文章目录 git查看记录查看文件修改列表查看修改差异友好的查看修改记录结合多个选项查看记录示例输出 git查看记录 使用 git log 你不仅可以查看提交记录&#xff0c;还可以通过一些选项查看文件的修改列表、修改差异&#xff0c;并以更友好的方式查看修改记录。以下是一些常用…...

检索增强生成RAG系列10--RAG的实际案例

讲了很多理论&#xff0c;最后来一篇实践作为结尾。本次案例根据阿里云的博金大模型挑战赛的题目以及数据集做一次实践。 完整代码地址&#xff1a;https://github.com/forever1986/finrag.git 本次实践代码有参考&#xff1a;https://github.com/Tongyi-EconML/FinQwen/ 目录 …...

程序员自我提升的全面指南

程序员自我提升的全面指南 1. 技术基础巩固重要性实践方法 2. 技术栈拓展重要性实践方法 3. 软技能提升重要性实践方法 4. 实践与项目经验重要性实践方法 5. 持续学习与职业规划重要性实践方法 6. 代码质量与优化重要性实践方法 7. 思维与创新能力重要性实践方法 8. 健康与心理…...

【golang】Golang手写元组 tuple | golang tuple

Golang手写元组 tuple 1、源码 如下&#xff1a; package tupletype Tuple[T any, U any] struct {First TSecond U }// zip combines elements of two slices into a slice of pairs (tuples), which is useful for combining related data. func Zip[T any, U any](slice…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例&#xff0c;Webpack.config.js它可能的配置和含义如下&#xff1a; 前言 Module Federation 的Webpack.config.js核心配置包括&#xff1a; name filename&#xff08;定义应用标识&#xff09; remotes&#xff08;引用远程模块&#xff0…...

Python训练营-Day26-函数专题1:函数定义与参数

题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一个名为 calculate_circle_area 的函数&#xff0c;该函数接收圆的半径 radius 作为参数&#xff0c;并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求&#xff1a;函数接收一个位置参数 radi…...