专栏:JavaEE初阶起飞计划

个人主页:手握风云

目录

一、多线程案例

1.1. 定时器


一、多线程案例

1.1. 定时器

        定时器是软件开发的一个重要组件,是一种能够按照预设的时间间隔或在特定时间点执行某个任务或代码片段的机制。你可以把它想象成一个闹钟,只不过这个“闹钟”不是提醒你去起床,而是提醒计算机去执行某个特定的操作。定时器与阻塞队列一致,也会被单独封装成一个或一组服务器来使用。

  • 标准库中的定时器
import java.util.Timer;
import java.util.TimerTask;public class Demo1 {public static void main(String[] args) {Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("定时器执行任务 3000");}}, 3000);timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("定时器执行任务 2000");}}, 2000);timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("定时器执行任务 1000");}}, 1000);System.out.println("程序启动");}
}

  • 定时器的实现

        对于自主实现的定时器,需要指定等待的最大时间,如果等不到,还需要执行其他的操作。

class MyTimer {public MyTimer() {}//向定时器中添加任务public void schedule(Runnable runnable, long delay) {}
}

        这里注意,TimerTask类实现的是Runnable接口,所以我们在schedule方法里面添加的也是Runnable类型的参数。既然要对任务进行组织管理,就得使用合适的数据结构,比如顺序表、栈。但是这些任务不一定是按照时间顺序添加的,并且添加的顺序和执行顺序没太大关系。如果使用顺序表,执行任务时,就需要遍历来找到时间最小的任务,效率太低。这时我们就可以使用堆来解决。

        对于堆所存放的泛型参数,这里不能添加成Runnable,因为堆里面的任务不只是内容,还需要考虑任务的时间。

class MyTimerTask {private Runnable task;// 这个地方为了和当前时间对比,确认任务是否执行,需要保存绝对的时间戳private long time;public MyTimerTask(Runnable task, long delay) {this.task = task;this.time = System.currentTimeMillis() + delay;}public Runnable getTask() {return task;}public long getTime() {return time;}
}class MyTimer {private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();public MyTimer() {}//向定时器中添加任务public void schedule(Runnable runnable, long delay) {queue.offer(new MyTimerTask(runnable, delay));}
}

        由于MyTimerTask是放在优先级队列中,所以我们还需要写出比较规则。

class MyTimerTask implements Comparable<MyTimerTask>{private Runnable task;// 这个地方为了和当前时间对比,确认任务是否执行,需要保存绝对的时间戳private long time;public MyTimerTask(Runnable task, long delay) {this.task = task;this.time = System.currentTimeMillis() + delay;}public Runnable getTask() {return task;}public long getTime() {return time;}@Overridepublic int compareTo(MyTimerTask o) {return (int) (this.time - o.time);}
}

        接下来就是创建线程,让线程来检测任务是否到时间了,以及去执行这个任务。我们需要循环从队列中取出元素,判断是否到时间了,如果到达就出队列,没有就不做处理。

import java.util.PriorityQueue;class MyTimerTask implements Comparable<MyTimerTask>{private Runnable task;// 这个地方为了和当前时间对比,确认任务是否执行,需要保存绝对的时间戳private long time;public MyTimerTask(Runnable task, long delay) {this.task = task;this.time = System.currentTimeMillis() + delay;}public Runnable getTask() {return task;}public long getTime() {return time;}@Overridepublic int compareTo(MyTimerTask o) {return (int) (this.time - o.time);}
}class MyTimer {private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();public MyTimer() {Thread t = new Thread(() -> {while (true) {if (queue.isEmpty()) {continue;}MyTimerTask task = queue.peek();long curTime = System.currentTimeMillis();if (curTime < task.getTime()) {continue;} else {task.getTask().run();queue.poll();}}});t.start();}//向定时器中添加任务public void schedule(Runnable runnable, long delay) {queue.offer(new MyTimerTask(runnable, delay));}
}public class Demo2 {public static void main(String[] args) {MyTimer timer = new MyTimer();timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("定时任务:3000");}}, 3000);timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("定时任务:2000");}}, 2000);timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("定时任务:1000");}}, 1000);}
}

        虽然执行效果没有什么问题,但上面的操作对于同一个队列进行出入,所以线程是不安全的。那我们就需要在入队列和出队列的操作里面都要进行加锁。第二个问题,就是忙等出现饿死。如上面的代码,当队列为空或者没到时间时,不做任何处理,只消耗CPU资源,没有任何实质性的进展。尤其是第二个continue,这里就相当于30分钟之后要去执行某项任务,每隔1分钟就得看一下时间,当我们设计了等待时间之后,到时间自动唤醒或者有优先级更高的任务要去执行。

        完整代码:

import java.util.PriorityQueue;class MyTimerTask implements Comparable<MyTimerTask>{private Runnable task;// 这个地方为了和当前时间对比,确认任务是否执行,需要保存绝对的时间戳private long time;public MyTimerTask(Runnable task, long delay) {this.task = task;this.time = System.currentTimeMillis() + delay;}public Runnable getTask() {return task;}public long getTime() {return time;}@Overridepublic int compareTo(MyTimerTask o) {return (int) (this.time - o.time);}
}class MyTimer {private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();private Object locker = new Object();public MyTimer() {Thread t = new Thread(() -> {while (true) {try {synchronized (locker) {if (queue.isEmpty()) {locker.wait();}MyTimerTask task = queue.peek();long curTime = System.currentTimeMillis();if (curTime < task.getTime()) {locker.wait(task.getTime() - curTime);} else {task.getTask().run();queue.poll();}}} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}//向定时器中添加任务public void schedule(Runnable runnable, long delay) {synchronized (locker) {queue.offer(new MyTimerTask(runnable, delay));locker.notify();}}
}public class Demo2 {public static void main(String[] args) {MyTimer timer = new MyTimer();timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("定时任务:3000");}}, 3000);timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("定时任务:2000");}}, 2000);timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("定时任务:1000");}}, 1000);}
}

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

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

相关文章

EDoF-ToF: extended depth of field time-of-flight imaging解读, OE 2021

1. 核心问题&#xff1a;iToF相机的“景深”死穴我们之前已经详细讨论过&#xff0c;iToF相机的“景深”&#xff08;有效测量范围&#xff09;受到光学散焦的严重制约。问题根源&#xff1a; 当iToF相机的镜头散焦时&#xff0c;来自场景不同深度的光信号会在传感器像素上发生…

符号引用与直接引用:概念对比与实例解析

符号引用与直接引用&#xff1a;概念对比与实例解析 符号引用和直接引用是Java虚拟机(JVM)中类加载与执行机制的核心概念&#xff0c;理解它们的区别与联系对于深入掌握Java运行原理至关重要。下面我将从定义、特性、转换过程到实际应用&#xff0c;通过具体示例全面比较这两类…

每日一讲——Podman

一、概念1、定义与定位Podman&#xff08;Pod Manager&#xff09;是符合OCI标准的容器引擎&#xff0c;用于管理容器、镜像及Pod&#xff08;多容器组&#xff09;。它无需守护进程&#xff08;Daemonless&#xff09;&#xff0c;直接通过Linux内核功能&#xff08;如命名空间…

Spring Boot DFS、HDFS、AI、PyOD、ECOD、Junit、嵌入式实战指南

Spring Boot分布式文件系统 以下是一些关于Spring Boot分布式文件系统(DFS)的实现示例和关键方法,涵盖了不同场景和技术的应用。这些示例可以帮助理解如何在Spring Boot中集成DFS(如HDFS、MinIO、FastDFS等)或模拟分布式存储。 使用Spring Boot集成HDFS 基础配置 // 配…

解决GoLand运行go程序报错:Error: Cannot find package xxx 问题

问题描述 一个简单的go程序&#xff0c;代码如下 package mainimport "fmt" func main() {// 占位符&#xff0c;和java的String.format用法一样fmt.Printf("我%d岁&#xff0c;我叫%s", 18, "yexindong") }结构如下当我想要运行时却报错 Error:…

Spring MVC设计精粹:源码级架构解析与实践指南

文章目录一、设计哲学&#xff1a;分层与解耦1. 前端控制器模式2. 分层架构设计二、核心组件源码解析1. DispatcherServlet - 九大组件初始化2. DispatcherServlet - 前端控制器&#xff08;请求处理中枢&#xff09;请求源码入口&#xff1a;FrameworkServlet#doGet()请求委托…

k8s之控制器详解

1.deployment&#xff1a;适用于无状态服务1.功能(1)创建高可用pod&#xff08;2&#xff09;滚动升级/回滚&#xff08;3&#xff09;平滑扩容和缩容2.操作命令&#xff08;1&#xff09;回滚# 回滚到上一个版本 kubectl rollout undo deployment/my-app# 回滚到特定版本&…

.NET Core中的配置系统

传统配置方式文件Web.config 进行配置。ConfigurationManager类配置。.NET配置系统中支持配置方式文件配置&#xff08;json、xml、ini等&#xff09;注册表环境变量命令行自定义配置源Json文件配置方式实现步骤&#xff1a;创建一个json文件&#xff0c;把文件设置 为“如果较…

kafka的消费者负载均衡机制

Kafka 的消费者负载均衡机制是保证消息高效消费的核心设计&#xff0c;通过将分区合理分配给消费者组内的消费者&#xff0c;实现并行处理和负载均衡。以下从核心概念、分配策略、重平衡机制等方面详细讲解。一、核心概念理解消费者负载均衡前&#xff0c;需明确三个关键概念&a…

腾讯云edges on部署pages

腾讯云edges on部署pages适用场景部署方式官方文档 适用场景 Next.js Hexo 以及用React Vue等现代前端框架构建的单页应用全栈项目开发 通过Pages Function KV等能力 实现轻量化的动态服务快速部署与迭代 通过Github等代码管理平台集成 每次代码提交时自动构建和部署网站 注…

SpringAI入门及浅实践,实战 Spring‎ AI 调用大模型、提示词工程、对话记忆、Adv‎isor 的使用

上一次写AI学习笔记已经好久之前了&#xff0c;温习温习&#xff0c;这一章讲讲关于Spring‎ AI 调用大模型、对话记忆、Adv‎isor、结构化输出、自定义对话记忆‍、Prompt 模板的相关知识点。 快速跳转到你感兴趣的地方一、提示词工程&#xff08;Prompt&#xff09;1. 基本概…

对抗攻击-知识点

文章目录自然图像往往靠近机器学习分类器学习到的决策边界&#xff08;decision boundaries&#xff09;。正交方向--改变某一个不影响其它的特征降采样&#xff08;Feature Downsampling&#xff09;通过黑盒攻击的持续挑战&#xff0c;我们才能构建真正安全可靠的智能系统DCT…

7.26 作业

一、实验要求及其拓扑图&#xff1a; 本次实验拓扑图&#xff1a; 二、实验IP地址划分&#xff1a; 1. 公网地址&#xff08;R5 作为 ISP&#xff0c;使用公网地址&#xff09;&#xff1a; R1 与 R5 之间接口&#xff1a;15.1.1.0/24&#xff0c;R1 侧为 15.1.1…

Kafka运维实战 14 - kafka消费者组消费进度(Lag)深入理解【实战】

目录什么是消费者 Lag举例说明&#xff1a;Lag 的意义&#xff1a;Lag 监控和查询kafka-consumer-groups基本语法常用命令示例1. 查看单个消费者组的详细信息&#xff08;最常用&#xff09;2. 列出所有消费者组&#xff08;只显示名称&#xff09;3. 列出所有消费者组&#xf…

设计模式(十三)结构型:代理模式详解

设计模式&#xff08;十三&#xff09;结构型&#xff1a;代理模式详解代理模式&#xff08;Proxy Pattern&#xff09;是 GoF 23 种设计模式中的结构型模式之一&#xff0c;其核心价值在于为其他对象提供一种间接访问的机制&#xff0c;以控制对原始对象的访问。它通过引入一个…

24点数学游戏(穷举法求解表达式)

摘要本毕业设计旨在利用MATLAB技术实现一个24点数学游戏&#xff0c;采用穷举法求解所有可能的表达式组合。通过全排列数字、枚举运算符及括号位置&#xff0c;结合递归回溯算法&#xff0c;系统能够高效地搜索所有可能的运算路径&#xff0c;并验证结果是否为24。实验结果表明…

【web应用】如何进行前后端调试Debug? + 前端JavaScript调试Debug?

文章目录一、前后端&#xff1a;后端以Debug模式运行后端项目&#xff0c;打断点二、前后端&#xff1a;前端项目在浏览器中调试三、单独前端&#xff1a;前端JavaScript调试1、控制台输出2、网页调试器中添加断点3、debugger关键字一、前后端&#xff1a;后端以Debug模式运行后…

FreeCAD开发楼梯参数化三维模型和钢格栅

根据楼梯标准图集开发各种楼梯。上行左转&#xff0c;上行右转&#xff0c;对应的栏杆也是配套2种。楼梯总成钢格栅标准里的跨度和承载 扁钢尺寸&#xff0c;轻松切换和修改参数。格栅综合本来格栅上横杆是冷轧扭钢筋&#xff0c;先绘制一个圆柱&#xff0c;再做一个内切正方形…

【AcWing 836题解】合并集合

AcWing 836. 合并集合 【题目描述】 在查看解析之前&#xff0c;先给自己一点时间思考哦&#xff01; 【题解】 并查集是一种用于处理集合合并与查询问题的数据结构&#xff0c;通常支持以下两种操作&#xff1a; Find&#xff1a;查询一个元素所在的集合。 Union&#xff1a…

MySQL锁机制与MVCC原理剖析

在MySQL中&#xff0c;我们使用到了它的各种类锁&#xff1b;按照它的维度&#xff0c;有各种锁 从数据库的操作粒度有&#xff0c;表锁&#xff0c;行锁。从数据库的操作的类型&#xff0c;有读锁和写锁。性能上有乐观锁和悲观锁。 在上一篇文章中的事务隔离级别&#xff0c;需…