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

多线程(JavaEE初阶系列5)

目录

前言:

1.什么是定时器

2.标准库中的定时器及使用

3.实现定时器

结束语:


前言:

在上一节中小编给大家介绍了多线程中的两个设计模式,单例模式和阻塞式队列模式,在单例模式中又有两种实现方式一种是懒汉模式,一种是饿汉模式,在这两种模式中我们推荐大家使用的是懒汉模式,虽然饿汉模式是天然的线程安全的,但是与饿汉模式相比起来效率没有懒汉模式的高。在阻塞式队列中给大家重点提到了生产者和消费者模型,这个是我们以后会经常用到的一种模式,当时小编为了大家好理解给大家举了两个例子一个是包饺子,一个就是三峡大坝的削峰填谷,希望大家重点理解这两个例子。这节中小编将给大家讲解一下多线程中的定时器,讲解一下什么是定时器,定时器的使用以及手动实现一个定时器。

1.什么是定时器

定时器也是软件开发中的一个重要的组件,类似于一个“闹钟”,达到一个设定的时间之后,就执行某个指定好的代码。

比如:网络通信中,如果对方500ms内没有返回数据,则断开连接尝试重连,比如一个Map,希望里面的某个key在3s之后过期(自动删除),类似于这样的场景就需要用到定时器。

2.标准库中的定时器及使用

在标准库中提供了一个类:Timer类。

Timer timer = new Timer( );

Timer类的核心方法为schedule。

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

timer.schedule( new TimerTack( ) {

        @Override

        public void run() {

                System.out.println("hello");

        }

} , 3000 );

下面我们就在idea中来给大家具体演示一下:

代码展示:

package Time;import java.util.Timer;
import java.util.TimerTask;public class ThreadDemo1 {public static void main(String[] args) {//创建一个定时器Timer timer = new Timer();//让hello4、hello3、hello2、hello1在线程启动之后分别在4s、3s、2s、1s之后执行。timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello4");}},4000);timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello3");}},3000);timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello2");}},2000);timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello1");}},1000);System.out.println("hello0");}
}

结果展示:

3.实现定时器

要想实现一个定时器我们就需要先来了解一下定时器的构成。

定时器的构成:

  • 是一个带优先级的阻塞队列。
  • 队列中的每一个元素是一个Task对象。
  • Task中带有一个时间属性,队首元素就是即将要执行的元素。
  • 同时有一个worker线程一直扫描队首元素,看队首元素是否需要执行。

这里给大家解释一下为啥要带优先级呢?

因为阻塞式队列中的任务都有各自执行时刻(delay),最先执行的任务一定是delay最小的,使用优先级的队列就可以高效的把这个delay最小的任务找出来了。所以这里的核心数据结构是“堆”!!!之前学习数据结构中的PriorityQueue就是一个带优先级的阻塞式队列。

注:具体的操作步骤请详细看代码内的注释!!!

代码展示:

package Time;import java.util.PriorityQueue;
class MyTask implements Comparable<MyTask>{public Runnable runnable;//为了方便后续的判定,使用绝对的时间戳public long time;public MyTask(Runnable runnable, long delay) {this.runnable = runnable;//取当前时刻的时间戳 + delay,作为该任务实际执行的时间戳。this.time = System.currentTimeMillis() + delay;}//指定一下在后续的优先级队列中我们是要按照时间来进行比较大小@Overridepublic int compareTo(MyTask o) {//这样的写法意味着每次取出的是时间最小的元素return (int) (this.time - o.time);}
}
//自己实现一个类似于Timer类的MyTimer
class MyTimer{//这个结构要求带有优先级的阻塞队列,核心数据结构就是“堆”。//PriorityQueue<> ———— <>里面的元素需要我们手动的封装一下,创建一个MyTask类,表示两方面的信息。1.执行的任务是啥。2.任务啥时候执行。private PriorityQueue<MyTask> queue = new PriorityQueue<>();//创建一个锁对象private Object locker = new Object();//此处的delay是一个形如3000这样的数字(指多长时间后执行该任务)public void schedule(Runnable runnable, long delay) {//根据参数,构造MyTask,插入队列即可。synchronized (locker) {synchronized (locker) {MyTask myTask = new MyTask(runnable, delay);queue.offer(myTask);locker.notify();}}}//在这里构造线程,负责执行具体的任务public MyTimer() {Thread t = new Thread(() -> {while (true) {try {synchronized (locker) {//阻塞队列,只有阻塞的入队列和阻塞的出队列,没有阻塞的查看队首元素。while (queue.isEmpty()) {locker.wait();}MyTask myTask = queue.peek();long curTime = System.currentTimeMillis();if (curTime >= myTask.time) {//时间到了,可以执行任务了queue.poll();myTask.runnable.run();} else {//时间还没到locker.wait(myTask.time - curTime);}}} catch (InterruptedException e) {e.printStackTrace();}}});//启动线程t.start();}
}
public class ThreadDemo2 {public static void main(String[] args) {//创建一个定时器对象MyTimer myTimer = new MyTimer();//模仿之前的使用方式使用myTimer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("hello4");}}, 4000);myTimer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("hello3");}}, 3000);myTimer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("hello2");}}, 2000);myTimer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("hello1");}}, 1000);System.out.println("hello0");}
}

结果展示:

可以看到上述代码的执行结果与标准库中定时器的效果一样。

结束语:

这节中小编带着大家一起了解了Java标准库中定时器的使用方式,并给大家实现了一下定时器。希望这节对大家学习JavaEE有一定的帮助,想要学习的同学记得关注小编和小编一起学习吧!如果文章中有任何错误也欢迎各位大佬及时为小编指点迷津(在此小编先谢过各位大佬啦!)

相关文章:

多线程(JavaEE初阶系列5)

目录 前言&#xff1a; 1.什么是定时器 2.标准库中的定时器及使用 3.实现定时器 结束语&#xff1a; 前言&#xff1a; 在上一节中小编给大家介绍了多线程中的两个设计模式&#xff0c;单例模式和阻塞式队列模式&#xff0c;在单例模式中又有两种实现方式一种是懒汉模式&a…...

Minimum Snap闭式求解相关公式推导

文章目录 1 M i n i m u m Minimum Minimum S n a p Snap Snap闭式求解的推导1.1 二次规划等式约束构建1.2 求 d d d1.3 转成无约束优化问题 1 M i n i m u m Minimum Minimum S n a p Snap Snap闭式求解的推导 可以看看我的这几篇Blog1&#xff0c;Blog2&#xff0c;Blog…...

Spring源码(五)— 解析XML配置文件(一) bean标签解析流程

前面几章的内容已经介绍了BeanFactory创建前的准备工作&#xff0c;以及加载XML配置文件前的准备的步骤。本章会着重介绍解析XML的步骤。 registerBeanDefinitions 前几个方法不做过多的赘述&#xff0c;着重看registerBeanDefinitions方法中解析XML的步骤。 public int regi…...

隐私政策声明

http://lxfamn.cn/tools 我们注重对您个人隐私的保护。有时候我们需要某些信息才能为您提供您请求的服务&#xff0c;本隐私声明解释了这些情况下的数据收集和使用情况。本隐私声明适用于本网站的所有相关服务。如果您访问本网站、使用本网站的任何服务&#xff0c;那么您便接受…...

Flutter 最佳实践和编码准则

Flutter 最佳实践和编码准则 视频 前言 最佳实践是一套既定的准则&#xff0c;可以提高代码质量、可读性和可靠性。它们确保遵循行业标准&#xff0c;鼓励一致性&#xff0c;并促进开发人员之间的合作。通过遵循最佳实践&#xff0c;代码变得更容易理解、修改和调试&#xff…...

LangChain Agents深入剖析及源码解密上(一)

LangChain Agents深入剖析及源码解密上(一) LangChain Agents深入剖析及源码解密上 Agent工作原理详解 本节会结合AutoGPT的案例,讲解LangChain代理(Agent)为核心的内容。我们前面已经谈了代理本身的很多内容,也看了绝大部分的源代码,例如:ReAct的源代码,还有mrkl的源代…...

css定义超级链接a标签里面的title的样式

效果: 代码: 总结:此css 使用于任何元素,不仅仅是a标签!...

hcip——路由策略

要求&#xff1a; 基础配置 AR1 [R1]int g 0/0/0 [R1-GigabitEthernet0/0/0]ip add 12.0.0.1 24[R1-GigabitEthernet0/0/0]int g 0/0/1 [R1-GigabitEthernet0/0/1]ip add 14.0.0.1 24[R1]int loop0 [R1-LoopBack0]ip add 1.1.1.1 24[R1]rip 1 [R1-rip-1]vers 2 [R1-rip-1]net…...

ReID网络:MGN网络(1) - 概述

Start MGN 1. 序言 现代基于感知的信息中&#xff0c;视觉信息占了80~85%。基于视觉信息的处理和分析被应用到诸如安防、电力、汽车等领域。 以安防市场为例&#xff0c;早在2017年&#xff0c;行业咨询公司IHS Market&#xff0c;我国在公共和私人领域安装有摄像头约1.76亿…...

C++数据结构笔记(10)递归实现二叉树的三序遍历

对于三种遍历方式来说&#xff0c;均为先左后右&#xff01;区别在于根结点的位置顺序 先序遍历&#xff1a;根——左——右 中序遍历&#xff1a;左——根——右 后序遍历&#xff1a;左——右——根 &#xff08;所谓先中后的顺序&#xff0c;是指根结点D先于子树还是后于…...

hMailServer-5.3.3-B1879.exe

hMailServer-5.3.3-B1879.exe...

后端校验JSR303

目录 一、导入依赖 二、实现步骤 三、分组校验 四、自定义校验 一、导入依赖 <dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId><version>2.0.1.Final</version></dependency> 二…...

vmware磁盘组使用率100%处理

今天在外办事时&#xff0c;有客户发过来一个截图&#xff0c;问vmware 磁盘组空间使用率100%咋办&#xff1f;如下图&#xff1a; 直接回复&#xff1a; 1、首先删除iso文件等 2、若不存在ISO文件等&#xff0c;找个最不重要的虚拟机直接删除&#xff0c;删除后稍等就会释放…...

Redis实战(3)——缓存模型与缓存更新策略

1 什么是缓存? 缓存就是数据交换的缓冲区&#xff0c; 是存贮数据的临时区&#xff0c;一般读写性能较高 \textcolor{red}{是存贮数据的临时区&#xff0c;一般读写性能较高} 是存贮数据的临时区&#xff0c;一般读写性能较高。缓存可在多个场景下使用 以一次 w e b 请求为例…...

python与深度学习(十):CNN和cifar10二

目录 1. 说明2. cifar10的CNN模型测试2.1 导入相关库2.2 加载数据和模型2.3 设置保存图片的路径2.4 加载图片2.5 图片预处理2.6 对图片进行预测2.7 显示图片 3. 完整代码和显示结果4. 多张图片进行测试的完整代码以及结果 1. 说明 本篇文章是对上篇文章训练的模型进行测试。首…...

剑指offer12 矩阵中的路径 13 机器人的运动范围 34.二叉树中和为某一值得路径

class Solution { public:bool exist(vector<vector<char>>& board, string word) {int rowboard.size(),colboard[0].size();int index0,i0,j0;if(word.size()>row*col) return 0;//vector<vector<int>> visit[row][col];//标记当前位置有没有…...

Pushgateway+Prometheus监控Flink

思路方案 FlinkMtrics->pushgateway->prometheus->grafnana->altermanager 方案 : Flink任务先将数据推到pushgateway。然后pushgateway将值推送到prometheus,最后grafana展示prometheus中的值, 去这个 https://prometheus.io/download/ 下载最新的 Prometheu…...

OpenCV图像处理-视频分割静态背景-MOG/MOG2/GMG

视频分割背景 1.概念介绍2. 函数介绍MOG算法MOG2算法GMG算法 原视频获取链接 1.概念介绍 视频背景扣除原理&#xff1a;视频是一组连续的帧&#xff08;一幅幅图组成&#xff09;&#xff0c;帧与帧之间关系密切(GOP/group of picture)&#xff0c;在GOP中&#xff0c;背景几乎…...

nginx 反向代理浅谈

前言 通常情况下&#xff0c;客户端向Web服务器发送请求&#xff0c;Web服务器响应请求并返回数据。而在反向代理中&#xff0c;客户端的请求不直接发送到Web服务器&#xff0c;而是发送到反向代理服务器。反向代理服务器会将请求转发给真实的Web服务器&#xff0c;Web服务器响…...

【概率预测】对风力发电进行短期概率预测的分析研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...