当前位置:网站首页>多线程案例——定时器
多线程案例——定时器
2022-08-01 12:46:00 【Living_Amethyst】
定时器是什么
定时器
也是软件开发中的一个重要组件. 类似于一个 “闹钟”. 达到一个设定的时间之后, 就执行某个指定好的代码.
定时器是一种实际开发中非常常用的组件.
比如网络通信中, 如果对方 500ms 内没有返回数据, 则断开连接尝试重连.
比如一个 Map, 希望里面的某个 key 在 3s 之后过期(自动删除).
类似于这样的场景就需要用到定时器
标准库中的定时器
- 标准库中提供了一个 Timer 类. Timer 类的核心方法为 schedule .
- schedule 包含两个参数. 第一个参数指定即将要执行的任务代码, 第二个参数指定多长时间之后
执行 (单位为毫秒).
示例:
public static void main(String[] args) {
// java.util 里的一个组件
Timer timer = new Timer();
//schedule这个方法的效果 是 “安排一个任务”
//不是立刻执行 而是3000毫秒之后执行
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("这是一个要执行的任务");
}
},3000);
}
模拟实现定时器
很多细节的解析再注释中注明
//模拟实现 定时器
import java.util.PriorityQueue;
import java.util.concurrent.PriorityBlockingQueue;
class MyTask implements Comparable<MyTask>{
//任务要干啥
private Runnable command;
//任务啥时候干
private long time; //绝对时间
public MyTask (Runnable command,long after){
this.command = command;
//此处记录的时间是一个绝对的时间戳,不是多长时间后执行
this.time = System.currentTimeMillis()+after;
}
//执行任务的方法 直接在内部调用 Runnable 的 run 即可
public void run(){
command.run();
}
public long getTime() {
return time;
}
@Override
public int compareTo(MyTask o) {
//希望时间小的在前 大的在后
return (int) (this.time - o.time);
}
}
class MyTimer {
//用来阻塞等待的锁对象
private Object locker = new Object();
//使用优先级队列来保存若干个任务
private PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();
// command:要执行的任务是啥
// after:多长时间之后执行这个任务
public void schedule(Runnable command,long after) {
MyTask myTask = new MyTask(command,after);
// 防止 新插入的任务 比之前队首的任务的时间还早,需要唤醒
synchronized (locker){
queue.put(myTask); //把加入操作也加锁
locker.notify();
}
}
public MyTimer(){
// 启动一个线程
Thread t = new Thread(()->{
while (true){
//循环过程中 不断尝试从队列中获取到队首元素
//判定队首元素当时的时间是否就绪,就绪了就执行 不就绪就不执行
try {
synchronized (locker) {
MyTask myTask = queue.take();//取的是队首元素,时间最早的任务
long curTime = System.currentTimeMillis();
if (myTask.getTime() > curTime) {
//时间还没到
queue.put(myTask); //把任务再放回队列
//队首的(最早执行的)元素时间还没到,需要等待,不然一直循环 CPU空转 内耗
locker.wait(myTask.getTime() - curTime);
} else {
//时间到了 执行任务
myTask.run();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
}
public class Demo18 {
public static void main(String[] args) {
MyTimer myTimer = new MyTimer();
myTimer.schedule(new Runnable() {
@Override
public void run() {
System.out.println("111");
}
},2000);
myTimer.schedule(new Runnable() {
@Override
public void run() {
System.out.println("222");
}
},4000);
myTimer.schedule(new Runnable() {
@Override
public void run() {
System.out.println("333");
}
},6000);
}
}
边栏推荐
- 2022 Go生态圈 rpc 框架 Benchmark
- sql中ddl和dml(数据库表与视图的区别)
- Qt获取文件夹下所有文件
- 找出相同属性值的对象 累加数量 汇总
- 数字证书原理
- pandas connects to the oracle database and pulls the data in the table into the dataframe, filters all the data from the current time (sysdate) to one hour ago (filters the range data of one hour)
- MySQL调优
- Js手写函数之new的模拟实现
- 如何成功通过 CKA 考试?
- LeetCode_位运算_简单_405.数字转换为十六进制数
猜你喜欢
随机推荐
MySQL调优
Simulation implementation of new of Js handwritten function
50W+小程序开发者背后的数据库降本增效实践
LeetCode_动态规划_中等_313.超级丑数
Aeraki Mesh 正式成为 CNCF 沙箱项目
MMF的初步介绍:一个规范化的视觉-语言多模态任务框架
如何获取微信视频号的地址(微信公众号的链接地址)
库函数的模拟实现(strlen)(strcpy)(strcat)(strcmp)(strstr)(memcpy)(memmove)(C语言)(VS)
LeetCode_动态规划_中等_377.组合总和 Ⅳ
安装apex报错
【倒计时5天】探索音画质量提升背后的秘密,千元大礼等你来拿
SQL functions STR
数字证书原理
线上问题排查常用命令,总结太全了,建议收藏!!
bat countdown code
(ES6 and above and TS) Map object to array
STM32 CAN过滤器配置详解
蔚来又一新品牌披露:产品价格低于20万
华盛顿大学、Allen AI 等联合 | RealTime QA: What's the Answer Right Now?(实时 QA:现在的答案是什么?)
How to get the address of WeChat video account (link address of WeChat public account)