[JAVAee]定时器

目录

定时器的含义

定时器的使用

定时器的解析

①TaskQueue

​②TimerThread

③Timer

定时器的模拟实现

①创建Task自定义类型

②创建TimerThread类

③Timer类

完整代码


定时器的含义

从名字上看,就是我们通俗理解的那个定时器.设置一定的时间,并在一定的时间后发生一定的操作.

定时器的使用

在java标准库中有一个Timer类实现了这个定时器

创建出Timer的实例后,使用Timer类中的schedule方法往其添加任务.

方法说明

public void schedule(TimerTask task, long delay)

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

关于第一个参数TimerTask类,其是继承了我们先前在多线程中Thread类中提到过了Runnable类.两者的使用方法和效果其实是大致相同的.

也要在TimerTask类中覆写run方法,说明要执行的任务.

值得我们注意的是,可以创建一个定时器实例后.不断了往里添加新的任务.

而不是一个定时器中只能包含有一个任务

Timer timer = new Timer();//创建一个实例对象
//调用schedule方法,并通过TimerTask的匿名内部类的方式覆写了其中的run方法
//在2秒后打印出"wow"与打印的时间点
timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("wow " + new Date());}
},2000);
//与上一致,在1秒后打印出"haha"与打印的时间点
timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("haha " + new Date());}
},1000);

定时器的解析

在java中,我们可以看到Timer类中主要为这三个类

①TaskQueue

其中TaskQueue是一个优先级队列,也称为堆.是一个以执行时间排序的小根堆.

关于使用优先级队列的原因:

时间本身就是一个很强烈的拥有前后顺序的一个数据.

假设11:00,12:00与13:00的时段分别设定一个定时器分别拥有三个任务.

在11:00时段还没有到达的时候,后面两个任务是永远永远不会先轮到他们启动的,所以对于在定时器中查看是否满足时间条件执行任务可以只观察第一个存放的数据,而不是每次都要将存储的数据全部遍历一遍来查看是否要执行相应的任务,达到了更高效的效果.

②TimerThread

在TimerThread类中,会创建出新的线程来负责检测扫描TaskQueue队列中的任务是否需要执行了.

当队列为空的时候,会调用wait方法变更为阻塞状态.

③Timer

在此类中,存放的就是Timer的构建方法,schedule方法等的实现.还会有一个标志位,判断queue队列中是否为空.

当队列为空时,TimerThread线程使用了wait方法为阻塞状态,在Timer中添加了新的数据后随即会调用相应的notify方法唤醒线程,开始扫描queue队列.

定时器的模拟实现

经过了一定解析后,我们对定时的模拟可以分成:

  1. 要有存放任务数据的数据结构
  2. 要有一个线程来负责扫描数据结构中存放的数据

因为是在定时器的实现是在多线程的环境下的,main主线程一个,自身也有一个TimerThread线程.

为了保证线程安全,我们数据结构可以使用阻塞队列来进行模拟实现.

①创建Task自定义类型

在此类中,实现的是任务类型Task的构造方法

class Task implements Comparable<Task>{private Runnable runnable;//使用Runnable类可以达到TimerTask的效果,都是存放定时器中要执行的任务private long time;//来记录任务执行的时间点public Task(Runnable runnable,long time){//重写Task的构造方法this.runnable = runnable;//创建新的Task时,要重写Runnable.this.time = System.currentTimeMillis() + time;//因为放入参数的时间都是一个时间段,而我们需要是时间点}public void run(){//启动任务runnable.run();}@Overridepublic int compareTo(Task o) {//自定义类型放入队列中,要记得重写比较方法噢return (int)(this.time - o.time);}}

②创建TimerThread类

实现对存放Task的优先级阻塞队列的扫描

private PriorityBlockingQueue<Task> queue = new PriorityBlockingQueue<>();private Object object = new Object();class TimerThread extends Thread{@Overridepublic void run() {while(true){try {Task task = queue.take();//从队列中取出队首元素long curTime = System.currentTimeMillis();if(task.time > curTime){//如果还没队首任务的时间则wait一段时间//并把取出查看的任务再塞回队列//要记住我们存放的数据结构是优先级队列,会自动排序噢queue.put(task);synchronized (object){//wait记得搭配synchronized使用//wait的时间为,当前时间到队首任务的时间之差wait(task.time - curTime);//这里的wait有了一段明确的时间,是不需要notify的}}else{//如果时间已经到了,就可以运行任务啦task.getRun();}} catch (InterruptedException e) {e.printStackTrace();break;//可以在这里写上break,因为while是true循环.//加上break,中断后可以直接跳出循环,就不会卡死了.}}}}

③Timer类

实现schedule方法

public class Timer {public Timer(){//构造方法TimerThread thread = new TimerThread();//扫描线程thread.start();//并启动}public void schedule(Runnable runnable,long time){//schedule方法,往队列中添加任务Task task = new Task(runnable,time);//创建Task类型的任务queue.put(task);//往队列中加入任务synchronized (object) {//在加入任务后,需要先唤醒线程.//此时线程可能因为还没到队首元素的时间调用了wait方法还在阻塞//新加入的任务的时间可能比队列中队首元素的任务的时间要早//所以需要唤醒线程重新扫描一遍队列,查看是否达到了时间object.notify();}}
}

完整代码

import java.util.concurrent.PriorityBlockingQueue;public class Timer{class Task implements Comparable<Task>{Runnable runnable;long time;public Task(Runnable runnable,long time){this.runnable = runnable;this.time = time;}public void getRun(){runnable.run();}@Overridepublic int compareTo(Task o) {return (int)(this.time - o.time);}}///private PriorityBlockingQueue<Task> queue = new PriorityBlockingQueue<>();private Object object = new Object();class TimerThread extends Thread{@Overridepublic void run() {while(true){try {Task task = queue.take();//从队列中取出队首元素long curTime = System.currentTimeMillis();if(task.time > curTime){//如果还没队首任务的时间则wait一段时间//并把取出查看的任务再塞回队列//要记住我们存放的数据结构是优先级队列,会自动排序噢queue.put(task);synchronized (object){//wait记得搭配synchronized使用//wait的时间为,当前时间到队首任务的时间之差wait(task.time - curTime);//这里的wait有了一段明确的时间,是不需要notify的}}else{//如果时间已经到了,就可以运行任务啦task.getRun();}} catch (InterruptedException e) {e.printStackTrace();break;//可以在这里写上break,因为while是true循环.//加上break,中断后可以直接跳出循环,就不会卡死了.}}}}/public Timer(){TimerThread thread = new TimerThread();thread.start();}public void schedule(Runnable runnable,long time){Task task = new Task(runnable,time);queue.put(task);synchronized (object) {object.notify();}}public static void main(String[] args) {Timer timer = new Timer();timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("wow");}},1000);timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("hahaha");}},2000);}
}

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

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

相关文章

安卓抓包神奇黄鸟HttpCanary安装配置及使用教程

1、下载安装包 黄鸟抓包下载地址 2、安装下载的apk 3、证书安装问题 vivo手机我安装时打开黄鸟app&#xff0c;会直接弹出&#xff0c;直接安装即可 其他手机&#xff0c;需要去系统设置中安装 3.1 搜索 证书&#xff0c;选择CA证书 3.2 进行本人操作验证 3.3 安装HttpCa…

黄东旭:The Future of Database,掀开 TiDB Serverless 的引擎盖

在 PingCAP 用户峰会 2023 上&#xff0c; PingCAP 联合创始人兼 CTO 黄东旭 分享了“The Future of Database”为主题的演讲&#xff0c; 介绍了 TiDB Serverless 作为未来一代数据库的核心设计理念。黄东旭 通过分享个人经历和示例&#xff0c;强调了数据库的服务化而非服务化…

C语言假期作业 DAY 01

题目 1.选择题 1、执行下面程序&#xff0c;正确的输出是&#xff08; &#xff09; int x5,y7; void swap() { int z; zx; xy; yz; } int main() { int x3,y8; swap(); printf("%d,%d\n"&#xff0c;x, y)…

Android Studio 代码模板插件实现

Android Studio 代码模板插件 背景 可以跳过背景和简述&#xff0c;从模板插件实现开始看. 开发新页面时&#xff0c;原先需要写一堆模板代码。比如用Databinding写列表结构的页面&#xff0c;需要手写以下文件&#xff1a; XxActivity.ktXxFragment.ktXxViewModel.ktXxListA…

基于K8s环境·使用ArgoCD部署Jenkins和静态Agent节点

今天是「DevOps云学堂」与你共同进步的第 47天 第⑦期DevOps实战训练营 7月15日已开营 实践环境升级基于K8s和ArgoCD 本文节选自第⑦期DevOps训练营 &#xff0c; 对于训练营的同学实践此文档依赖于基础环境配置文档&#xff0c; 运行K8s集群并配置NFS存储。实际上只要有个K8s集…

CAD .NET 15.0 企业版 Crack

CAD .NET 15.0 企业版 企业版 企业版 企业版 企业版 Updated: June 14, 2023 | Version 15.0 NEW CAD .NET is a library for developing solutions in .NET environment. It supports AutoCAD DWG/ DXF, PLT and other CAD formats. The library can be used in a wide rang…

C语言之pthread_cond_t信号变化探究总结(八十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

【RabbitMQ(day2)】默认(直连)交换机的应用

文章目录 一、第一种模型&#xff08;Hello World&#xff09;二、第二种模型&#xff08;work queue&#xff09;自动确认机制的后果和公平分配 三、阐述默认交换机 这篇博客是以下资料学后的总结&#xff1a; 不良人的RabbitMQ的教学视频 官方启动教程 RabbitMQ中文文档 一、…

【SQL语句】

目录 一、SQL语句类型 1.DDL 2.DML 3.DLL 4.DQL 二、数据库操作 1.查看 2.创建 2.1 默认字符集 2.2 指定字符集 3.进入 4.删除 5.更改 5.1 库名称 5.2 字符集 三、数据表操作 1.数据类型 1.1 数值类型&#xff08;常见&#xff0c;下同&#xff09; 1.1.1 T…

ChatGPT长文本对话输入方法

ChatGPT PROMPTs Splitter 是一个开源工具&#xff0c;旨在帮助你将大量上下文数据分成更小的块发送到 ChatGPT 的提示&#xff0c;并根据如何处理所有块接收到 ChatGPT&#xff08;或其他具有字符限制的语言模型&#xff09;的方法。 推荐&#xff1a;用 NSDT设计器 快速搭建可…

【QT】Day3

1. 完成闹钟的实现&#xff1a; widgt.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug> #include <QTimerEvent> //定时器事件处理函数 #include <QTime> //时间类 #include <QTextToSpeech> //文本转语音类头…

Jmap-JVM(十六)

上篇文章说了ZGC是jdk11加入的&#xff0c;他是未来jvm垃圾收集器的奠定者&#xff0c;满足TB级别内存处理&#xff0c;STW时间保持在10ms以下。 Jmap 我们可以先通过jmap -histo 进程ip 来查看&#xff0c;但是这样看不太清晰&#xff0c;我们可以用这行命令生成一个文件&…

机器学习:GPT3

GPT3 模型过于巨大 GPT3是T5参数量的10倍&#xff01; 训练GPT3的代价是$12百万美元 Zero-shot Ability GPT3的思想是不是能拿掉Fine-tune 只需要给定few-shot或者zero-shot就能干相应的任务了。 few-shot learning&#xff08;no gradient descent&#xff09;&#…

9.python设计模式【外观模式】

内容&#xff1a;为子系统中的一组接口提供一个一致的界面&#xff0c;外观模式定义了一个高层接口&#xff0c;这个接口使得这一个子系统更加容易使用。 角色&#xff1a; 外观&#xff08;facade&#xff09;子类系统&#xff08;subsystem classes&#xff09; UML图 举…

容器化安装环境EFK搭建

容器化安装环境 Docker中安装并启动ElasticSearch 前置配置 第一步&#xff1a;在宿主机上执行echo “net.ipv4.ip_forward1” >>/usr/lib/sysctl.d/00-system.conf 2.第二步&#xff1a;重启network和docker服务 [rootlocalhost /]# systemctl restart network &&…

使用低代码开发,需要注意哪些?

低代码平台的历史相对较短&#xff0c;大约始于 2000 年初&#xff0c;源于快速应用程序开发工具。随着低代码平台和工具的日益普及和优势&#xff0c;它不断发展以满足各种领域和角色的需求。 本文将研究各种低代码和无代码应用程序开发方法、业务用例、挑战和未来预测等。 一…

论文浅尝 | 预训练Transformer用于跨领域知识图谱补全

笔记整理&#xff1a;汪俊杰&#xff0c;浙江大学硕士&#xff0c;研究方向为知识图谱 链接&#xff1a;https://arxiv.org/pdf/2303.15682.pdf 动机 传统的直推式(tranductive)或者归纳式(inductive)的知识图谱补全(KGC)模型都关注于域内(in-domain)数据&#xff0c;而比较少关…

UEditor 百度富文本编辑器使用 遇到问题

小小吐槽 碰到前后不分离项目&#xff0c;富文本使用的UEdtior UEditor 点击上传图片转base64 在ueditor.all.js文件中找到这个 callback()函数 这里使用根据图片的url转成base64 UEditore 粘贴图片转base64 UEditor回显图片&#xff08;base64&#xff09; 把ueditor.all…

Java面向对象编程实战详解(图书管理系统示例)

文章目录 面向编程概念图书管理系统示例需求分析设计阶段编码实现创建目录结构Book类的编码BookList类的编码User类的编码AdminUser类的编码NormalUser类的编码启动类的编写具体的操作实现IOperation接口新增图书的实现借阅图书的实现删除图书的实现显示图书的实现查找图书的实…

使用C#基于ComPDFKit SDK快速构建PDF阅读器

在当今世界&#xff0c;Windows 应用程序对我们的工作至关重要。随着处理 PDF 文档的需求不断增加&#xff0c;将 ComPDFKit PDF 查看和编辑功能集成到您的 Windows 应用程序或系统中&#xff0c;可以极大地为您的用户带来美妙的体验。 在本博客中&#xff0c;我们将首先探索集…