目录
- 定时器是什么
- 标准库中的定时器
- 模拟实现定时器
- 为什么不用阻塞队列中的优先级队列
定时器是什么
- 定时器也是软件开发中的⼀个重要组件. 类似于⼀个 “闹钟”. 达到⼀个设定的时间之后, 就执⾏某个指定任务
- ⽐如⽹络通信中, 如果对⽅ 500ms 内没有返回数据, 则断开连接尝试重连
标准库中的定时器
- 标准库里面提供了一个Timer类, Timer类的核心方法是schedule(安排的意思)
- schedule包含了个参数, 第一个参数是要执行的任务, 第二个参数是多久后执行(对于现在时间, 单位我为毫秒)
- 第一个参数要重写TimerTask任务接口的run方法执行任务
- 定时器里面内置了线程来执行这些任务
public class demo34 {public static void main(String[] args) throws InterruptedException {Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello 3000");}}, 3000);timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello 2000");}}, 2000);timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("hello 1000");}}, 1000);System.out.println("hello main");Thread.sleep(4000);timer.cancel();}
}
- 这里用cancel来结束主线程, 因为我们定时器默认创建的是一个前台线程(也就是非守护线程). 前台线程不结束完, 进程也就不会结束
模拟实现定时器
class MyTimerTask implements Comparable<MyTimerTask>{private Runnable runnable; private long time; public MyTimerTask(Runnable runnable, long delay){this.runnable = runnable;this.time = delay;}public long getTime(){return time;}public void run(){runnable.run(); }@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(() -> {try {while (true) {synchronized (locker) { MyTimerTask task = queue.peek(); while (task == null) {locker.wait(); task = queue.peek();}long curTime = System.currentTimeMillis();if(curTime >= task.getTime()){task.run();queue.poll(); }else{locker.wait(task.getTime() - curTime); }}}}catch (InterruptedException e) {e.printStackTrace();}});t.start();}public void schedule(Runnable runnable, long delay){synchronized (locker){ MyTimerTask myTimerTask = new MyTimerTask(runnable, delay);queue.add(myTimerTask);locker.notify(); }}
}

public class demo35 {public static void main(String[] args) {MyTimer timer = new MyTimer();timer.schedule(() -> {System.out.println("hello 3000");}, 3000);timer.schedule(() -> {System.out.println("hello 2000");}, 2000);timer.schedule(() -> {System.out.println("hello 1000");}, 1000);}
}
为什么不用阻塞队列中的优先级队列
- 阻塞队列内置了锁, 这个时候我们自己也加了一把锁. 如果形成死锁条件(请求和保持)或者循环等待就成死锁了. 所以我们没必要冲冒这个风险
