【JavaEE】多线程(6) -- 定时器的使用及实现

目录

定时器是什么

标准库中的定时器的使用

实现定时器


定时器是什么

Java中的定时器是一种机制,用于在预定时间执行某个任务。它允许开发人员在指定的时间间隔内重复执行任务,或在指定的延迟之后执行任务。定时器是Java提供的一种方便的工具,用于处理需要定期执行的任务,例如定时任务调度、定时数据备份等。

定时器也是软件开发中的⼀个重要组件. 类似于⼀个 "闹钟". 达到⼀个设定的时间之后, 就执⾏某个指定好的代码

定时器是⼀种实际开发中⾮常常⽤的组件.

⽐如⽹络通信中, 如果对⽅ 500ms 内没有返回数据, 则断开连接尝试重连.

⽐如⼀个 Map, 希望⾥⾯的某个 key 在 3s 之后过期(⾃动删除).

类似于这样的场景就需要⽤到定时器.

标准库中的定时器的使用

标准库中提供了⼀个 Timer 类. Timer 类的核心方法为 schedule .

schedule 包含两个参数: 第一个参数指定即将要执行的任务代码, 第⼆个参数指定多长时间之后执行 (单位为毫秒).

public static void main(String[] args) {Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello 3000");}},3000);timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello 2000");}},2000);timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello 1000");}},1000);System.out.println("hello main");}

 

第一个任务在3000毫秒(3秒)后执行,它的run方法会打印出"hello 3000"。
第二个任务在2000毫秒(2秒)后执行,它的run方法会打印出"hello 2000"。
第三个任务在1000毫秒(1秒)后执行,它的run方法会打印出"hello 1000"。 

实现定时器

定时器的构成

• ⼀个带优先级队列(不要使用 PriorityBlockingQueue, 容易死锁!)

• 队列中的每个元素是⼀个 Task 对象.

• Task 中带有⼀个时间属性, 队首元素就是即将要执行的任务

• 同时有⼀个 worker 线程⼀直扫描队首元素, 看队首元素是否需要执行

创建以下两个类来实现定时器的功能:

1. MyTimer 类提供的核⼼接⼝为 schedule, ⽤于注册⼀个任务, 并指定这个任务多⻓时间后执⾏.

class MyTimer {public void shedule(Runnable runnable, long delay) {}
}

2. Task 类⽤于描述⼀个任务(作为 Timer 的内部类). ⾥⾯包含⼀个 Runnable 对象和⼀个 time(毫秒时 间戳) 这个对象需要放到优先队列 中. 因此需要实现 Comparable 接⼝

class MyTimerTask implements Comparable<MyTimerTask> {public MyTimerTask(Runnable runnable, long delay) {}public void run() {runnable.run();}@Overridepublic int compareTo(MyTimerTask o) {return (int)(this.time - o.time);}
}

Runnable是Java中一个非常重要的接口,它是一个函数式接口,用于定义线程的任务。Runnable接口只包含一个抽象方法run(),该方法是线程的入口点,线程在执行时会调用run()方法中的代码。 

下面是具体的实现过程:

//通过这个类来描述一个任务
class MyTimerTask implements Comparable<MyTimerTask> {//time是一个 ms 级别的时间戳private long time;//实际任务要执行的代码private Runnable runnable;public long getTime() {return time;}public MyTimerTask(Runnable runnable, long delay) {this.runnable = runnable;//计算一下真正要执行任务的绝对时间, 使用绝对时间,方便判定任务是否达到时间this.time = System.currentTimeMillis() + delay;}public void run() {runnable.run();}@Overridepublic int compareTo(MyTimerTask o) {return (int)(this.time - o.time);}
}//通过一个类表示一个任务的进程
class MyTimer {// 负责扫描任务队列, 执行任务的线程private Thread t = null;//任务队列private PriorityQueue<MyTimerTask>queue = new PriorityQueue<>();//锁对象private Object locker = new Object();public void shedule(Runnable runnable, long delay) {synchronized (locker) {MyTimerTask task = new MyTimerTask(runnable,delay);queue.offer(task);//添加新的元素后, 就可以唤醒扫描线程的 wait 了;locker.notify();}}public void cancel() {// 结束t线程// interrupt}//构造方法, 创建扫描线程, 让扫描线程来完成判定和执行public MyTimer() {t = new Thread(() -> {//扫描线程就需要循环反复的扫描队首元素, 然后判定队首元素是不是时间到了//如果时间没到, 啥都不干//如果时间到了, 就执行这个任务并且把这个任务从队列中删除掉while(true) {try {synchronized (locker) {while (queue.isEmpty()) {locker.wait();}MyTimerTask  task = queue.peek();long curTime = System.currentTimeMillis();if(curTime >= task.getTime()) {//当前时间已经达到了任务执行时间, 就可以执行任务了queue.poll();task.run();} else {// 当前时间还没有到, 暂时先不执行// 不能使用sleep, 会错过新的任务, 也无法释放锁locker.wait(task.getTime() - curTime);}}}catch (InterruptedException e) {e.printStackTrace();}}});t.start();}
}

在 MyTimer 的构造方法中, 需要注意加锁的位置:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2660076.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

图分割算法之贪心算法

1 贪心算法的思想 Linear Deterministic Greedy partitioning (LDG)考虑在分割的时候将邻居结点放置在一起&#xff0c;以减少切割边。它采用贪心算法将一个结点放置在包含其邻居最多的子图中&#xff0c;同时保证每个子图的结点负载均衡&#xff0c;整个算法流程图如下其中 C …

单文件超过4GB就无法拷贝到U盘?这个你一定要知道

前言 随着现在科技发展&#xff0c;小伙伴们所使用的数据也越变越大。还记得WindowsXP流行的时候&#xff0c;XP的镜像文件仅为几百MB大小。 但是现在随便一个系统就有可能超过4GB。 如果单个文件超过4GB就有可能没办法拷贝进U盘&#xff0c;在这里就需要给小伙伴们普及一下U…

用ChatGPT挑选钻石!著名珠宝商推出-珠宝GPT

根据Salesforce最新发布的第五版《互联网购物报告》显示&#xff0c;ChatGPT等生成式AI的出现、快速发展&#xff0c;对零售行业和购物者产生了较大影响。可有效简化业务流程实现降本增效&#xff0c;并改善购物体验。 著名珠宝商James Allen为了积极拥抱生成式AI全面提升销售…

vue2使用svg图片

1、安装依赖包&#xff1a; npm install svg-sprite-loader --save-dev 2、新建assets/icons/svg中放置svg图片和index.js文件 svgo.yml文件 index.js import Vue from vue import SvgIcon from /components/SvgIcon// svg component// register globally Vue.component(sv…

antd中DatePicker禁选范围如何设置

1、解决日期禁选问题 在官方api中也提到&#xff0c;可以设置disabledDate来实现日期的禁选 语法&#xff1a; js中定义disabledData函数 const disabledDate (current) > { 设置禁选范围 } 在DatePicker 标签中引入 同时我们要知道antd是默认使用moment.js来实现日期格式…

【ES】es介绍

倒排索引&#xff08;Inverted Index&#xff09;和正排索引&#xff08;Forward Index&#xff09; 正排索引是一种以文档为单位的索引结构&#xff0c;它将文档中的每个单词或词组与其所在的文档进行映射关系的建立。正排索引通常用于快速检索指定文档的内容&#xff0c;可以…

Python列表数据处理全攻略(三):常用内置方法轻松掌握

文章目录 引言Python列表常用内置方法count()功能介绍语法示例注意事项 index()功能介绍语法示例注意事项&#xff1a; insert()功能介绍语法示例注意事项总结 结束语 引言 亲爱的读者&#xff0c;你好&#xff01;Python的列表在数据结构中占据着核心地位&#xff0c;对于学习…

k8s-cni网络 10

Flannel vxlan模式跨主机通信原理 在同一个节点上的pod 流量通过cni网桥可以直接进行转发&#xff1b; 在需要跨主机访问时&#xff0c;数据包通过flannel(隧道) 知道另一边的mac地址&#xff0c;就可以拿到另一边的ip地址&#xff0c;然后构建常规的以太网数据包&#xff0c;…

github登录需要双因素认证(Two-factor authentication)

前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 github登录需要双因素认证&#xff08;Two-factor authentication&#xff09; 今天登录github发现需要绑定双因素才能够登录 我们…

具有权威性的工信部证书怎么考

工信部证书的考试流程如下&#xff1a; 选择正规报考机构&#xff1a;选择一家权威的培训机构或考试中心&#xff0c;确保其具有相应的资质和经验。 提交个人报考资料&#xff1a;根据考试机构的要求&#xff0c;提交相关的个人报考资料&#xff0c;如身份证、学历证明、工作…

【单片机项目实战】温度控制系统

本项目的主要作用是实现温度调控&#xff0c;通过设定一个预定的温度值&#xff0c;实现实时检测外界温度&#xff0c;当外界温度小于预定值时&#xff0c;电机正转&#xff0c;实现降温效果&#xff1b;当外界温度大于预定值时&#xff0c;电机反转&#xff0c;实现升温效果&a…

SpringBoot多线程与任务调度总结

一、前言 多线程与任务调度是java开发中必须掌握的技能&#xff0c;在springBoot的开发中&#xff0c;多线程和任务调度变得越来越简单。实现方式可以通过实现ApplicationRunner接口&#xff0c;重新run的方法实现多线程。任务调度则可以使用Scheduled注解 二、使用示例 Slf…

TiDB SQL调优案例TiFlash

背景 早上收到某系统的告警tidb节点挂掉无法访问&#xff0c;情况十万火急。登录中控机查了一下display信息&#xff0c;4个TiDB、Prometheus、Grafana全挂了&#xff0c;某台机器hang死无法连接&#xff0c;经过快速重启后集群恢复&#xff0c;经排查后是昨天上线的某个SQL导…

2022年全球软件质量效能大会(QECon北京站2022)-核心PPT资料下载

一、峰会简介 当前&#xff0c;新一轮科技革命和产业变革正在重塑全球经济格局&#xff0c;以云计算为代表的新一代信息技术创新活跃&#xff0c;与实体经济深度融合&#xff0c;推动泛在连接、数据驱动、智能引领的数字经济新形式孕育而生。 新兴技术的出现给测试乃至整个软…

小米路由器2(R2D) 安装 MIXBOX

1. 先刷开发版 ROM http://www1.miwifi.com/miwifi_download.html 进入上述网页&#xff0c;找到 R2D 点击下载 开发版 ROM 教程 看 下载按钮上边的 “刷机教程” 刷机教程 2. 开启SSH工具 登录自己的小米账号后&#xff0c;里面会显示出 自己的 root密码&#xff1b; 默认…

记一次修复外网无法访问vmware里面的虚拟机的网络端口的问题

发现一个奇怪的网络问题&#xff0c;vmware里一个程序的端口通过vmnat穿透出来&#xff0c;然后这个端口就能够通过局域网被其他机器访问&#xff0c;但是另一个网段就没法访问这个端口。使用主机上的其他程序使用开启同样的端口&#xff0c;另一个网段的机器却可以访问。我想不…

Android Security PIN 相关代码

开发项目遇到一个问题&#xff0c;具体描述及复制步骤如下&#xff1a; 就是开启"Enhanced PIN privacy"(增强的PIN隐私)的时候输入秘密的时候还是会显示数字 如下图&#xff0c;应该是直接是“.” 不应该出现PIN 密码 想要的效果如下图&#xff1a; 设置的步骤如下图…

中职网络安全Server2002——Web隐藏信息获取

B-2&#xff1a;Web隐藏信息获取 任务环境说明&#xff1a; 服务器场景名&#xff1a;Server2002&#xff08;关闭链接&#xff09;服务器场景用户名&#xff1a;未知 有问题需要环境加q 通过本地PC中渗透测试平台Kali使用Nmap扫描目标靶机HTTP服务子目录&#xff0c;将扫描子…

用户规模破亿!基于文心一言的创新应用已超4000个

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

Matter协议解析记录

目录 目录 1、Matter 协议发展 1.1、什么是Matter 1.2、Matter能做什么 2、整体介绍 3、架构介绍 3.1、Matter网络拓扑结构 3.2、功能解析 3.2.1、Fabric引用和Fabric标识符 3.2.2、供应商标识符&#xff08;Vendor ID&#xff0c;VID&#xff09; 3.2.3、产品标识符…