JavaWeb~教你如何自己实现一个定时器

  1. 需要一个Task类来描述一段逻辑或者说是一个要执行的任务 同时要记录这个任务在啥时候执行

// 优先队列中的元素必须是可比较的~

// 比较规则的指定主要是两种方式:

// 1. 让 Task 实现 Comparable 接口

// 2. 让优先队列构造的时候, 传入一个比较器对象 (Comparator).

static class Task implements Comparable {

// Runnable 中有一个 run 方法, 就可以借助这个 run 方法来描述要执行的具体的任务是啥.

private Runnable command;

// time 表示啥时候来执行 command, 是一个绝对时间(ms级别的时间戳)

private long time;

// 构造方法的参数表示: 多少毫秒之后执行. (相对时间) 这个相对时间的参数是为了用起来方便

public Task(Runnable command, long after) {

this.command = command;

this.time = System.currentTimeMillis() + after;

}

// 执行任务的具体逻辑

public void run() {

command.run();

}

@Override

public int compareTo(Task o) {

// 谁的时间小(先执行)

return (int) (this.time - o.time);

}

}

  1. 需要使用一个阻塞优先级队列组织所有的任务 判断谁先执行 谁后执行

static class Timer {

// 为了避免忙等, 需要使用 wait 方法.

// 使用一个单独的对象来辅助进行 wait

// 使用 this 也行.

private final Object mailBox = new Object();

// 定时器的基本构成, 有三个部分.

// 1. 用一个类来描述 “任务”

// 2. 用一个阻塞优先队列来组织若干个任务. 让队首元素就是时间最早的任务.

// 如果队首元素时间未到, 那么其他元素也肯定不能执行.

private PriorityBlockingQueue queue = new PriorityBlockingQueue<>();

// 3. 用一个线程来循环扫描当前的阻塞队列的队首元素, 如果时间到, 就执行指定的任务.

public Timer() {

// 创建线程

Worker worker = new Worker(queue, mailBox);

worker.start();

}

// 4. 还需要提供一个方法, 让调用者能把任务给 “安排” 进来.

// schedule => 安排

public void schedule(Runnable command, long after) {

Task task = new Task(command, after);

queue.put(task);

synchronized (mailBox) {

//防止新加进来的任务执行优先级是最高的 就去唤醒等待中的线程 让其去执行优先级最高的任务

mailBox.notify();

}

}

}

  1. 还需要一个扫描线程 循环扫描判断队列的队首元素是不是到时间了需要执行了 如果需要执行了就执行该任务

static class Worker extends Thread {

private PriorityBlockingQueue queue;

private final Object mailBox;

public Worker(PriorityBlockingQueue queue, Object mailBox) {

this.queue = queue;

this.mailBox = mailBox;

}

@Override

public void run() {

// 实现具体的线程执行的内容

while (true) {

try {

// 1. 取出队首元素, 检查时间是否到了

Task task = queue.take();

// 2. 检查当前任务时间是否到了

long curTime = System.currentTimeMillis();

if (task.time > curTime) {

// 时间还没到~, 就把任务再塞回队列中

queue.put(task);

synchronized (mailBox) {

//为了避免忙等 就直接让该线程等待到时间到 然后去自动唤醒

mailBox.wait(task.time - curTime);

}

} else {

task.run();

}

} catch (InterruptedException e) {

e.printStackTrace();

break;

}

}

}

}

完整代码+测试

======================================================================

import java.util.concurrent.PriorityBlockingQueue;

public class Timer {

//添加一个公共用对象去实现wait和唤醒

private final Object loker = new Object();

//首先需要一个类Task去描述一个任务

//使用阻塞优先级队列来组织若干个线程判断谁先执行

private PriorityBlockingQueue blockingQueue = new PriorityBlockingQueue<>();

//用一个线程去循环扫描当前队列的队首元素 如果时间到了就执行该任务

public Timer() {

Worker worker = new Worker(blockingQueue, loker);

//启动worker里的线程

worker.start();

}

//计时器还需要一个方法让用户往里放任务

public void schedule(Runnable runnable, long time) {

Task task = new Task(runnable, time);

blockingQueue.put(task);

//新进来任务要唤醒wait的线程让优先级队列重新组织去判断哪个先执行

synchronized (loker) {

loker.notify();

}

}

}

//因为要放到优先级阻塞队列所有要实现Compararble接口

class Task implements Comparable {

//在这类去描述一个线程任务 所以他需要你个Runnable和time去确定什么时候执行

private Runnable runnable;

private long time;

public Task(Runnable runnable, long after) {

this.runnable = runnable;

this.time = System.currentTimeMillis() + after;

}

//提供一个run方法执行Runnable

public void run() {

runnable.run();

}

public long getTime() {

return time;

}

@Override

public int compareTo(Task o) {

//要让时间小的先去执行

return (int) (this.time - o.time);

}

}

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
…(img-Sn3EsMdt-1715713839976)]

[外链图片转存中…(img-21rnSLPU-1715713839977)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值