java - 定时器
一、什么是定时器
定时器是指可以通过 Java 中的 Timer 类和 TimerTask 类所提供的功能来实现定期执行某些任务的工具。
标准库中提供了一个 Timer 类 . Timer 类的核心方法为 schedule .schedule 包含两个参数 . 第一个参数指定即将要执行的任务代码 , 第二个参数指定多长时间之后执行 ( 单位为毫秒).下面是一个示例代码,用于创建一个定时器, 5 秒钟后打印一条消息:
import java.util.Timer; import java.util.TimerTask; public class TimerExample { public static void main(String[] args) { Timer timer = new Timer(); timer.schedule(new TimerTask() { public void run() { System.out.println("5 秒钟已经过去了..."); } }, 5000); } }
在上述代码中,我们首先创建一个 Timer 对象,然后使用 schedule 方法安排一个 TimerTask 对象在 0 秒后开始运行, 5 秒钟后再次运行。在 TimerTask 的 run 方法中,我们打印了一条简单的消息。
总之,Java 中的定时器是一种可以用来实现定期执行某些任务的工具,在开发中,我们可以根据具体需求来设计和使用相应的定时器,来进行任务的调度和处理。
二、实现定时器
定时器的构成 :
- 一个带优先级的阻塞队列
为啥要带优先级呢?
因为阻塞队列中的任务都有各自的执行时刻 (delay). 最先执行的任务一定是 delay 最小的. 使用带优先级的队列就可以高效的把这个 delay 最小的任务找出来.- 队列中的每个元素是一个 MyTask 对象.
- MyTask 中带有一个时间属性, 队首元素就是即将
- 同时要创建线程一直扫描队首元素, 看队首元素是否需要执行
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;
}
@Override
public int compareTo(MyTask o) {
return (int)(this.time-o.time);
}
}
public class MyTimer {
//带有优先级的阻塞队列
private PriorityBlockingQueue<MyTask> priorityBlockingQueue = new PriorityBlockingQueue<>();
private Object locker = new Object();
public void schedule(Runnable runnable,long delay){
MyTask task = new MyTask(runnable,delay);
//放任务
priorityBlockingQueue.put(task);
synchronized (locker) {
locker.notify();
}
}
public MyTimer(){
Thread t = new Thread(() -> {
while(true){
synchronized (locker) {
try {
//取任务
MyTask take = priorityBlockingQueue.take();
//任务的时间
Long curTime = System.currentTimeMillis();
if(take.time <= curTime){
//时间到了,可以执行任务
take.runnable.run();
}else{
//时间没到,把任务重新放回到队列里
priorityBlockingQueue.put(take);
//
locker.wait(take.time-curTime);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
}
}