【JavaEE】多线程案例 - 定时器
作者主页:paper jie_博客
本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。
本文于《JavaEE》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将MySQL基础知识一网打尽,希望可以帮到读者们哦。
其他专栏:《MySQL》《C语言》《javaSE》《数据结构》等
内容分享:本期将会分享多线程案例 - 定时器
目录
什么是定时器
Java标准库中的定时器 - Timer
自定义一个定时器
定时器的组成
描述类MyTask
实现MyTask的比较
MyTimer类的构架
schedule方法
内置线程
线程安全与wait等待
具体代码
代码执行流程
什么是定时器
定时器是我们程序猿来软件开发中一个很重要的组件.它的作用就是和闹钟一样. 当达到一个设定的时间后,就需要去执行某段指定的代码.定时器在我们实际开发中特别常见.比如一款游戏需要联网才能使用,要是在1秒之内没有数据返回给服务器,这时定时器就会发挥作用,断开与网络的连接然后尝试重连.
Java标准库中的定时器 - Timer
在我们Java标准库中就内置了一个Timer类,他就是定时器. 它里面有一个核心方法schedule就是用来注册任务的.
schedule里面有两个参数. 一个是时间到了需要执行的代码, 第二个是需要等待的时间,单位是毫秒.
public class ThreadDemo11 {public static void main(String[] args) {Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello 1000");}}, 1000);}
}
自定义一个定时器
定时器的组成
这里用一个MyTimer类来表示定时器
1) 需要一个存放任务的优先级队列PriorityQueue
2) 需要一个MyTask类来描述任务
3) 这些任务是需要比较时间的,MyTask类需要实现Comparable接口
4) 需要定义一个内置线程来不断扫描任务观察时间到了没
5) 需要实现核心方法schedule来注册任务
描述类MyTask
Task这个类用来描述任务,里面包含一个Runnable对象和一个time时间戳. 需要执行的代码会通过传参的形式给到Runnable.
class MyTask3 {//private long time;private Runnable runnable = null;public MyTask3(Runnable runnable, long delay) {this.runnable = runnable;//需要执行的时刻this.time = System.currentTimeMillis() + delay;}//获取时间public long getTime() {return time;}//获取需要执行的代码public void run() {runnable.run();}}
实现MyTask的比较
因为Mytask是描述任务,而这些任务需要放到优先级队列中比较,就需要实现Comparable或者比较器.这里我们实现Comparable接口.
class MyTask3 implements Comparable<MyTask3>{//private long time;private Runnable runnable = null;public MyTask3(Runnable runnable, long delay) {this.runnable = runnable;//需要执行的时刻this.time = System.currentTimeMillis() + delay;}//获取时间public long getTime() {return time;}//获取需要执行的代码public void run() {runnable.run();}//比较时间快慢方法@Overridepublic int compareTo(MyTask3 o) {return (int)(this.time - o.time);}
}
MyTimer类的构架
这里最核心的就是priorityQueue这个优先级队列,用它来存放我们的任务. 所对象为我们后面起到一个加锁的作用.
class MyTimer3 {//用优先级队列来存放任务private PriorityQueue<MyTask3> priorityQueue = new PriorityQueue<>();//锁对象private Object blocker = new Object();public void schedule(Runnable runnable, long time) {//核心方法}
}
schedule方法
这里我们在核心方法schedule中创建出一个任务,再将这个任务放入优先级队列中.
public void schedule(Runnable runnable, long time) {//创建一个任务MyTask3 myTask3 = new MyTask3(runnable, time);//将创建的任务放入优先级队列中priorityQueue.offer(myTask3);}
内置线程
这里将内置线程放入构造方法中,当这个类一创建就开始执行. 这里通过while循环来不断扫描.
//内置线程public MyTimer3() {//创建一个线程Thread t = new Thread(() -> {//通过while来不断扫描while(true) {//判断优先级队列是不是空的if(priorityQueue.isEmpty()) {//为空就等待//continue;}//当优先级队列中有任务时,取出任务MyTask3 myTask3 = priorityQueue.peek();//当前时间long time = System.currentTimeMillis();//如果到时间了就执行if(time >= myTask3.getTime()) {myTask3.run();priorityQueue.take();}else {//时间没到等待//continue;}}});t.start();}
线程安全与wait等待
这里发现schedule方法和构造方法都会有对于priorityQueue优先级队列的读和修改,这里可能就会出现线程安全问题,我们就需要为他们加上锁. 为空时我们就通过wait方法等待,等调用schedule方法使用notify唤醒它. 当有元素时但时间没到也是使用wait有时间的等待,时间到了就解除等待.
public void schedule(Runnable runnable, long time) {synchronized (blocker) {//创建一个任务MyTask3 myTask3 = new MyTask3(runnable, time);//将创建的任务放入优先级队列中priorityQueue.offer(myTask3);//通过notify来唤醒扫描线程blocker.notify();}}//内置线程public MyTimer3() {//创建一个线程Thread t = new Thread(() -> {//通过while来不断扫描while(true) {//加锁synchronized (blocker) {try {//判断优先级队列是不是空的if(priorityQueue.isEmpty()) {//为空就等待blocker.wait();}//当优先级队列中有任务时,取出任务MyTask3 myTask3 = priorityQueue.peek();//当前时间long time = System.currentTimeMillis();//如果到时间了就执行if(time >= myTask3.getTime()) {myTask3.run();priorityQueue.poll();}else {//时间没到等待 通过wait等待 有时间的等待.blocker.wait(myTask3.getTime() - time);}}catch(InterruptedException o) {o.printStackTrace();}}}});//启动线程t.start();}
具体代码
class MyTask3 implements Comparable<MyTask3>{//private long time;private Runnable runnable = null;public MyTask3(Runnable runnable, long delay) {this.runnable = runnable;//需要执行的时刻this.time = System.currentTimeMillis() + delay;}//获取时间public long getTime() {return time;}//获取需要执行的代码public void run() {runnable.run();}//比较时间快慢方法@Overridepublic int compareTo(MyTask3 o) {return (int)(this.time - o.time);}
}class MyTimer3 {//用优先级队列来存放任务private PriorityQueue<MyTask3> priorityQueue = new PriorityQueue<>();//所对象private Object blocker = new Object();//核心方法public void schedule(Runnable runnable, long time) {synchronized (blocker) {//创建一个任务MyTask3 myTask3 = new MyTask3(runnable, time);//将创建的任务放入优先级队列中priorityQueue.offer(myTask3);//通过notify来唤醒扫描线程blocker.notify();}}//内置线程public MyTimer3() {//创建一个线程Thread t = new Thread(() -> {//通过while来不断扫描while(true) {//加锁synchronized (blocker) {try {//判断优先级队列是不是空的if(priorityQueue.isEmpty()) {//为空就等待blocker.wait();}//当优先级队列中有任务时,取出任务MyTask3 myTask3 = priorityQueue.peek();//当前时间long time = System.currentTimeMillis();//如果到时间了就执行if(time >= myTask3.getTime()) {myTask3.run();priorityQueue.poll();}else {//时间没到等待 通过wait等待 有时间的等待.blocker.wait(myTask3.getTime() - time);}}catch(InterruptedException o) {o.printStackTrace();}}}});//启动线程t.start();}
}
代码执行流程

相关文章:
【JavaEE】多线程案例 - 定时器
作者主页:paper jie_博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文于《JavaEE》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造&…...
网络小测------
使用软件PT7.0按照上面的拓扑结构建立网络,进行合理配置,使得所有计算机之间能够互相通信。并且修改各交换机的系统名称为:学号_编号,如你的学号为123,交换机Switch0的编号为0,则系统名称为123_0࿱…...
基于linux系统的Tomcat+Mysql+Jdk环境搭建(二)jdk1.8 linux 上传到MobaXterm 工具的已有session里
【JDK安装】 1.首先下载一个JDK版本 官网地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 下载1.8版本,用红框标注出来了: 也许有的同学看到没有1.8版本,你可以随便下载一个linux的…...
04-Nacos中负载均衡规则的配置
负载均衡规则 同集群优先 默认的ZoneAvoidanceRule实现并不能根据同集群优先的规则来实现负载均衡,Nacos中提供了一个实现叫NacosRule可以优先从同集群中挑选服务实例 当服务消费者在本地集群找不到服务提供者时也会去其他集群中寻找,但此时会在服务消费者的控制台报警告 第…...
Kotlin 中的 `use` 关键字:优化资源管理(避免忘记inputStream.close() ?)
在 Android开发中,正确且高效地管理资源是至关重要的。use 关键字在 Kotlin 中为资源管理提供了一个简洁且强大的解决方案。它主要用于自动管理那些需要关闭的资源,比如文件、网络连接等。 一、use 关键字的工作原理 🤖 use 是一个扩展函数…...
时序预测 | Python实现GRU-XGBoost组合模型电力需求预测
时序预测 | Python实现GRU-XGBoost组合模型电力需求预测 目录 时序预测 | Python实现GRU-XGBoost组合模型电力需求预测预测效果基本描述程序设计参考资料预测效果 基本描述 该数据集因其每小时的用电量数据以及 TSO 对消耗和定价的相应预测而值得注意,从而可以将预期预测与当前…...
扁平化菜单功能制作
网页效果: HTML部分: <body><ul class"nav"><li><a href"javascript:void(0);">菜单项目一</a><ul><li>子菜单项01</li><li>子菜单项02</li><li>子菜单项03<…...
网络基础——路由协议及ensp操作
目录 一、路由器及路由表 1.路由协议: 2.路由器转发原理: 3.路由表: 二、静态路由优缺点及特殊静态路由默认路由 1.静态路由的优缺点: 2.下一跳地址 3.默认路由 三、静态路由配置 四、补充备胎 平均负载 五、补充&…...
Python-折线图可视化
折线图可视化 1.JSON数据格式2.pyecharts模块介绍3.pyecharts快速入门4.创建折线图 1.JSON数据格式 1.1什么是JSON JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装数据JSON本质上是一个带有特定格式的字符串 1.2主要功能json就是一种在各个编程语言中流…...
C++类与对象 (上)
目录 前言: 类和对象的理解 类的引入 类的定义与使用方式 访问限定符 类的两种定义方式 成员变量的命名规则 类的作用域 类的实例化 类对象模型 计算类对象的大小 类对象的存储方式 this指针 前言: C语言是面向过程的,关注的是过…...
no module named ‘xxx‘
目录结构如下 我想在GCNmodel的model里引入layers的GraphConvolution:from GCNmodel.layers import GraphConvolution,但这样却报错no module named GCNmodel,而且用from layers import GraphConvolution也不行。然后用sys.path.appen(xxx)…...
Go实现MapReduce
背景 当谈到处理大规模数据集时,MapReduce是一种备受欢迎的编程模型。它最初由Google开发,用于并行处理大规模数据以提取有价值的信息。MapReduce模型将大规模数据集分解成小块,然后对这些小块进行映射和归约操作,最终产生有用的…...
Axure的交互样式和情形
Axure的交互样式和情形 交互样式 Axure是一个流行的原型设计工具,它允许您创建交互式原型,模拟应用程序或网站的功能和用户界面。在Axure中,您可以设置各种交互样式来使原型更加生动和真实。 链接触发器:通过给一个元素添加链接…...
Mybatis在新增某个数据后,如何获取新增数据的id
在某些业务中,我们在新增一条数据之后,需要拿到这条数据的id来对这条数据进行后续的一个操作,如何拿取id呢? 使用的是<insert> 中的useGeneratedKeys 和 keyProperty 两个属性 1.在Mybatis Mapper文件中添加属性 “useGene…...
12.4~12.14概率论复习与相应理解(学习、复习、备考概率论,这一篇就够了)
未分配的题目 概率计算(一些转换公式与全概率公式)与实际概率 ,贝叶斯 一些转换公式 相关性质计算 常规,公式的COV与P 复习相关公式 计算出新表达式的均值,方差,再套正态分布的公式 COV的运算性质 如…...
关于多重背包的笔记
多重背包可以看作01背包的拓展, 01背包是选或者不选。多重背包是选0个一直到选s个。 for (int i 1; i < n; i) {for (int j m; j > w[i]; --j){f[j] max(f[j], f[j - 1*w[i]] 1*v[i], f[j - 2*w[i]] 2*v[i],...f[j - s*w[i]] s*v[i]);} } 由上述伪代码…...
如何使用 Java 的反射
如何使用 Java 的反射? 通过一个全限类名创建一个对象 Class.forName(“全限类名”); 例如:com.mysql.jdbc.Driver Driver 类已经被加载到 jvm 中,并且完成了类的初始化工作就行了 类名.class; 获取 Class<?> clz 对象对…...
PLC-Recorder V3 修改服务器和客户端通讯端口的方法
PLC-Recorder V3是服务器和客户端的架构,他们之间用TCP通讯。如果客户端无法与服务器建立连接(重启也无效,并且确保没有老版本的PLC-Recorder在运行),则可能是端口被占用了。这时候需要修改他们之间的通讯端口…...
libevent服务GET/POST的简单使用
目录 1、前言2、测试demo2.1、目录结构2.2、 测试源码2.2.1、http_server.cpp2.2.2、 http_server.h 2.3、 编译2.4、 运行结果2.4.1、测试POST2.4.2 、测试GET请求 1、前言 项目开发中经常需要使用到私有协议和Qt,Android等GUI前端通信,比较常用的使用POST和GET方式…...
MySQL 系列:注意 ORDER 和 LIMIT 联合使用的陷阱
文章目录 前言背后的原因ORDER BY 排序列存在相同值时返回顺序是不固定的LIMIT 和 ORDER BY 联合使用时的行为ORDER BY 或 GROUP BY 和 LIMIT 联合使用优化器默认使用有序索引 如何解决其它说明个人简介 前言 不知道大家在在分页查询中有没有遇到过这个问题,分页查…...
Java 8 Optional搭配flatMap,如何优雅地避免NPE链式调用?一个完整案例讲透
Java 8 Optional搭配flatMap:彻底解决嵌套对象空指针问题的工程实践 在Java开发中,处理多层嵌套对象的属性访问时,空指针异常(NullPointerException)就像房间里的大象——人人都知道存在,却常常选择视而不见…...
SWMM复杂城市排水系统模型及排水防涝、海绵城市设计等工程实践应用与二次开发
随着计算机的广泛应用和各类模型软件的发展,将排水系统模型作为城市洪灾评价与防治的技术手段已经成为防洪防灾的重要技术途径。美国环保局的雨水管理模型(SWMM),是当今世界最为著名的排水系统模型。SWMM能模拟降雨和污染物质经过…...
Loop:Mac免费窗口管理神器,彻底告别桌面混乱的终极解决方案
Loop:Mac免费窗口管理神器,彻底告别桌面混乱的终极解决方案 【免费下载链接】Loop Window management made elegant. 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop 你是否曾因Mac桌面上堆满的窗口而感到困扰?当多个应用程序…...
掌控AMD Ryzen性能:5步精通SMUDebugTool硬件调试技巧
掌控AMD Ryzen性能:5步精通SMUDebugTool硬件调试技巧 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://git…...
【ElevenLabs有声书量产指南】:从零到上线的7步闭环流程(含避坑清单+API调优参数)
更多请点击: https://intelliparadigm.com 第一章:ElevenLabs有声书量产的底层逻辑与场景定位 ElevenLabs 的有声书量产并非简单调用 TTS API,而是依托其神经语音建模、上下文感知韵律合成与批量异步编排三重能力构建的工业化流水线。其底层…...
为什么迅雷下载比浏览器稳?从原理到实战的完整使用手册
目录 为什么迅雷下载比浏览器稳?从原理到实战的完整使用手册 前言 一、核心原理:为什么迅雷下载断网也不怕? 1. 断点续传:下载到一半断网也能续 2. 多线程下载:同时开多个 “下载通道” 3. P2P 分布式加速&#…...
数学竞赛资源合集
《高中数学•竞赛教程》四册(第三版) 文件大小: 1.1GB内容特色: 四册高清笔记真题拆解,省队教练亲授适用人群: 想一年冲省一的高一高二竞赛党核心价值: 刷完这套,一试二试不再丢分下载链接: https://pan.quark.cn/s/7a64da5c8d8d 浙大优学-高中数学竞赛…...
半导体行业如何应对政策不确定性:从游说策略到企业决策
1. 从一篇旧报道看半导体行业的“华盛顿困局”最近整理资料时,翻到一篇2012年EE Times的旧文,标题是《硅谷国度:选举后的政治僵局或将持续——SIA CEO如是说》。文章不长,但里面半导体行业协会(SIA)时任CEO…...
C++多线程编程:深入剖析std::thread的使用方法
一、线程std::thread简介std::thread 是 C11 中引入的一个库,用于实现多线程编程。它允许程序创建和管理线程,从而实现并发执行。std::thread 在 #include<thread>头文件中声明,因此使用 std::thread 时需要包含 #include<thread>…...
别再裸奔了!手把手教你给Nacos 2.x加上用户密码和权限隔离(附Spring Boot配置)
Nacos 2.x安全加固实战:从零构建企业级权限体系 在微服务架构快速迭代的初期,许多团队为了开发效率往往选择"裸奔"模式运行Nacos——不开启任何鉴权机制。这种看似便捷的做法实则暗藏巨大风险:配置信息泄露、服务被恶意注销、敏感数…...
