【Java | 多线程案例】定时器的实现

个人主页:兜里有颗棉花糖
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创
收录于专栏【Java系列专栏】【JaveEE学习专栏】
本专栏旨在分享学习JavaEE的一点学习心得,欢迎大家在评论区交流讨论💌

这里写目录标题

  • 一、Timer定时器
  • 二、Timer定时器的设计
  • 三、定时器的实现
  • 四、总结

一、Timer定时器

Java中,Timer类是用于计划和执行重复任务的类(Java标准库中确实提供了java.util.Timer类)。它可以在指定的时间间隔内重复执行一个任务,或者在指定时间点执行任务。

二、Timer定时器的设计

选择java.util包中的Timer类:
在这里插入图片描述

在这里插入图片描述
使用了Timer类的schedule()方法来安排一个任务在延迟3000毫秒后执行。在TimerTask的run()方法中,我们编写需要执行的具体任务逻辑
我们现在来了解一下TimerTask()这个抽象类(如下图):该类是一个抽象类,并且继承了Runnable方法创建了一个匿名内部类并实现了run()方法。这个匿名内部类可以被认为是继承了TimerTask抽象类,并提供了具体的实现代码。
在这里插入图片描述
调用timer.schedule()方法注册的任务,会由Timer内部的线程池去执行,而不是由调用schedule()方法的线程直接执行run()方法。
Timer类内部创建了一个线程池,用于执行注册的定时任务。当调用schedule()方法后,Timer会将传入的TimerTask对象添加到线程池中进行调度。

下面是一个简单的定时器程序,可以运行试试看:

import java.util.Timer;
import java.util.TimerTask;public class Demo22 {public static void main(String[] args) {Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello world!!!");}},3000);System.out.println("程序开始执行喽!!!");}
}

运行结果如下:
在这里插入图片描述
可以看到程序并没有结束进程,原因如下:
Timer内部有自己的线程,为了保证随时处理新安排的任务,此线程会一直持续的执行,即此线程影响了阻止来整个进程的结束。

定时器是支持多个任务同时执行的,请看:
在这里插入图片描述
在这里插入图片描述

三、定时器的实现

代码实现如下:

import java.util.Comparator;
import java.util.PriorityQueue;class MyTimerTask implements Comparable<MyTimerTask> {private long time; // 表示任务什么时候开始执行private Runnable runnable; // 表示具体任务是啥public MyTimerTask(Runnable runnable,long delay) {// delay是一个相对的时间差time = System.currentTimeMillis() + delay;// 这里计算出任务执行的具体时间this.runnable = runnable;}public long getTime() {return time;}public Runnable getRunnable() {return runnable;}@Overridepublic int compareTo(MyTimerTask o) {// 时间最少的元素放在队首,即时间越少优先级越高return (int)(this.time - o.time); // time是long类型}
}// 这是定时器类的本体
class MyTimer {// 使用优先级队列来保存上面的N个任务private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();// locker是用来加锁的对象private Object locker = new Object();// 定时器的核心方法,即把要执行的任务添加到队列中public void schedule(Runnable runnable,long delay) {synchronized (locker) {MyTimerTask task = new MyTimerTask(runnable,delay);queue.offer(task);// 每次来新的任务之后都会唤醒一下扫描线程,此时扫描线程就可以根据最新的任务情况来重新规划等待时间locker.notify();}}// MyTimer类中还需要一个扫描线程,一方面要负责检查队首元素是否是此时应该被执行的。// 另一方面,当任务到点开始执行之后,需要调用Runnable中的run方法来完成任务public MyTimer() {// 扫描线程Thread 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.getRunnable().run(); // 至此就可以执行该任务了} else {// 如果当前时间早于任务的执行时间,诶呀太早了,让这个线程(休眠)休息一会一会吧!!!// Thread.sleep(task.getTime() - curTime);locker.wait(task.getTime() - curTime);}}} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}}public class Demo23 {public static void main(String[] args) {MyTimer timer = new MyTimer();timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("hello world! 3");}},3000);timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("hello world! 2");}},2000);timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("hello world! 1");}},1000);System.out.println("程序开始执行!!!");}
}

运行结果如下:
在这里插入图片描述

四、总结

Timer类是Java中的定时工具类,它可以帮助我们实现在指定时间执行指定任务的功能。Timer类提供了一个方法即schedule方法,我们可以通过schedule方法来注册一个任务并指定执行该任务的时间,当执行时间到的时候,Timer类内部的线程就会负责调用执行注册的任务。

另外我们可以通过优先级队列的方式来实现类似于Timer类这样的定时器。

本文到这里就结束了,希望友友们可以支持一下一键三连哈。嗯,就到这里吧,再见啦!!!

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot快速搭建一个简易商城项目【完成登录功能且优化】

完成登录且优化&#xff1a; 未优化做简单的判断&#xff1a; 全部异常抓捕 优化&#xff1a;返回的是json的格式 BusinessException&#xff1a;所有的错误放到这个容器中&#xff0c;全局异常从这个类中调用 BusinessException&#xff1a; package com.lya.lyaspshop.exce…

2020年认证杯SPSSPRO杯数学建模A题(第一阶段)听音辨位全过程文档及程序

2020年认证杯SPSSPRO杯数学建模 A题 听音辨位 原题再现&#xff1a; 把若干 (⩾ 1) 支同样型号的麦克风固定安装在一个刚性的枝形架子上 (架子下面带万向轮&#xff0c;在平地上可以被水平推动或旋转&#xff0c;但不会歪斜)&#xff0c;这样的设备称为一个麦克风树。不同的麦…

starrocks集群fe/be节点进程守护脚本

自建starrocks集群&#xff0c;有时候服务会挂掉&#xff0c;无法自动拉起服务&#xff0c;于是采用supervisor进行进程守护。可能是版本的原因&#xff0c;supervisor程序总是异常&#xff0c;无法对fe//be进行守护。于是写了个简易脚本。 #!/bin/bash AppNameFecom.starrock…

模型 安索夫矩阵

本系列文章 主要是 分享模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。产品市场战略。 1 安索夫矩阵的应用 1.1 江小白的多样化经营策略 使用安索夫矩阵来分析江小白市场战略。具体如下&#xff1a; 根据安索夫矩阵&#xff0c;江小白的现有产品是其白酒产品&…

缓存cache和缓冲buffer的区别

近期被这两个词汇困扰了&#xff0c;感觉有本质的区别&#xff0c;搜了一些资料&#xff0c;整理如下 计算机内部的几个部分图如下 缓存&#xff08;cache&#xff09; https://baike.baidu.com/item/%E7%BC%93%E5%AD%98 提到缓存&#xff08;cache&#xff09;&#xff0c;就…

OpenAI“一路生花”,致力于超级人工智能研发

原创 | 文 BFT机器人 INTELLIGENT ROBOT OpenAI提供1000万美元的资助用于解决超级智能AI控制问题 OpenAI是人工智能研究领域的领先组织&#xff0c;据媒体称&#xff0c;它正在采取积极措施应对与超级智能AI系统相关的潜在风险。在一项大胆的举措中&#xff0c;该公司宣布将提…

独立站如何优化网页加载速度

对于跨境电商独立站而言&#xff0c;流量是跨境电商业务的重中之重&#xff0c;由于独立站并不自带流量&#xff0c;非常依赖于谷歌搜索引擎自然流量&#xff0c;以及付费广告流量。 但随着付费流量价格日益水涨船高&#xff0c;为了摆脱对付费流量的依赖&#xff0c;相信广大…

可移动磁盘上的文件删除了怎么恢复?详细教程介绍

在我们的日常生活和工作中&#xff0c;可移动磁盘作为一种便携式的存储设备&#xff0c;经常被用来备份和传输数据。然而&#xff0c;有时候由于误操作或不小心的删除&#xff0c;导致可移动磁盘上的文件丢失。这些文件可能包含重要的工作资料、个人照片、视频等&#xff0c;一…

【YOLO系列】YOLOv8 -【教AI的陶老师】

文章目录 yolo v8 模型结构图这样搞有什么意义&#xff1f;【获得不同尺寸的输出】c2f 详细结构yolo v8 损失函数与 yolo v5 的区别 yolo v8 模型结构图 详细结构图 这样搞有什么意义&#xff1f;【获得不同尺寸的输出】 c2f 详细结构 yolo v8 损失函数 与 yolo v5 的区别

第1章 Kali Linux入门

本章将带领读者初步了解渗透测试专用的独立Linux 操作系统——Kali Linux。本章涵盖下述主题&#xff1a; ● Kali 的发展简史&#xff1b; ● Kali 的一般用途&#xff1b; ● Kali 的下载与安装&#xff1b; ● Kali 的配置与更新。 在本章的结尾部分&#xff0c;我们还…

【进阶】【JS逆向爬虫】【2.JavaScript 基础语法】JS代码导入方式

JS逆向爬虫 JS代码导入方式1.行内式写法2.内嵌式&#xff08;建议写在</body>之前&#xff09;3.外部式&#xff08;建议写在</head>之前&#xff09; JS代码导入方式 1.行内式写法 可以将单行或少量 JS 代码写在HTML标签的事件属性中&#xff08;以 on 开头的属…

【计算机网络】第五,六章摘要重点

1.运输层协议概述 运输层提供的是进程之间的通信 2. 3.套接字指的是什么 ip地址端口号 4.每一条TCP语句唯一地被通信两端连接的两个端点 5.TCP传输如何实现 以字节为单位的滑动窗口 超时重传 选择确认 6.TCP流量控制和拥塞控制的区别 流量控制&#xff1a;点对点通信…

Cisco模拟器-OSPF路由协议

设计要求用两台双口路由器连接不同IP网段的计算机&#xff0c;并使用OSFP协议发现路由表使不同IP网段的计算机可以相互通信。 通过设计&#xff0c;可以连通IP地址网段不同的局域网&#xff0c;可应用在园区网的互连和互通的实现上。 主要配置步骤 路由器0&#xff1a; Router…

24、Web攻防——通用漏洞SQL注入MYSQL跨库ACCESS偏移

文章目录 一、SQL注入原理   脚本代码在与数据库进行数据通讯时&#xff08;从数据库取出相关数据进行页面显示&#xff09;&#xff0c;使用预定义的SQL查询语句进行数据查询。能通过参数传递自定义值来实现SQL语句的控制&#xff0c;执行恶意的查询操作&#xff0c;例如查询…

C# 使用ZXing.Net生成带Logo的二维码

写在前面 这是ZXing.Net类库的系列文章&#xff0c;实现在二维码中间插入一个logo图标 C# 使用ZXing.Net生成二维码和条码-CSDN博客 C# 使用ZXing.Net识别二维码和条码-CSDN博客 代码实现 该段代码主体来自其他文章&#xff0c;贴在这做个记录 /// <summary> /// 生成…

【教程】Typecho Joe主题开启并修复壁纸相册不显示问题

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 背景说明 Joe主题本身支持“壁纸”功能&#xff0c;其实就是相册。当时还在网上找了好久相册部署的开源项目&#xff0c;太傻了。 但是网上教程很少&#xff0c;一没说如何开启壁纸功能&#xff0c;二没说开启后为…

2023年终总结:耕辍断续应犹在,碌而不暇仍少年

Author&#xff1a;AXYZdong 硕士在读 工科男 有一点思考&#xff0c;有一点想法&#xff0c;有一点理性&#xff01; 定个小小目标&#xff0c;努力成为习惯&#xff01;在最美的年华遇见更好的自己&#xff01; CSDNAXYZdong&#xff0c;CSDN首发&#xff0c;AXYZdong原创 唯…

精品Nodejs实现的校园疫情防控管理系统的设计与实现健康打卡

《[含文档PPT源码等]精品Nodejs实现的校园疫情防控管理系统的设计与实现[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; 操作系统&#xff1a;Windows 10、Windows 7、Win…

Docker 概述以及整体架构

文章目录 一、Docker概述1.1 什么是 Docker1.2 Docker 如何工作1.3 底层技术 二、Docker架构2.1 Docker 整体架构2.2 Docker daemon2.3 Docker client2.4 Docker registries2.5 Docker objects2.6 Docker Desktop 参考资料 一、Docker概述 1.1 什么是 Docker Docker是一个用于…