首先创建一个定时器类MyTimer和一个任务类Task(具体任务,和多久开始跑任务)
任务类Task先实现这些基本字段和构造方法
定时器里面定义一个优先级队列来放这些任务(本质最小堆,把时间最短的任务放在最上面,达到拿取任务为最近任务目的),写一个schedule方法来把这些任务put进队列
说明一下BlockingQueue是线程安全的并且实现了带有优先级队列的版本
具体实现内容就是传入任务和多久时间的参数,里面实例化一个任务,再将任务put进最小堆里.
但由于不知道队首元素是否为时间最小的任务,所以需要在定时器里创建一个扫描线程来不停地扫描这个优先级阻塞队列队首是否为最小值(因为不知道操作系统是否在这段时间又添加了新任务而且时间还更早)
用lambda表达式创建扫描线程,一个while(true)循环take取出队首元素 再把当前时间与设定时间比较(可能会报错,原因后面解释)根据结果判断时间是否到了来继续后面操作任务的实现.
定义一个当前时间curTime,然后比较一下当前时间与设定最小时间的任务时间比较(如果当前时间大于等于超过了闹钟时间)则需要执行任务了(task.getRunnable().run())否则再把任务塞回去(时间没到噻)
写到这就差不多完成了定时器的大致轮廓了,但还有修改的地方:
先在main函数里实例化一个定时器跑起来看看:调用定时器timer的schedule安排任务方法创建任务,一个任务在3秒后将要开始啦!!
结果不出意外的出现了报错:
看这个Comparable说明我们没有指定多个任务时间的比较方法.这需要一个接口来实现统一一下
比较方式(在Task任务类中实现)
需得实现一个Comparable接口(带上Task泛型哦),刚实现接口后这个类会爆红(因为没有重写这个任务的比较方法)按住alt+enter键有一个import的红色来导入然后重写就好了:
但需要long强转int(任务是long,方法返回值是int的):
现在差不多都可以跑定时器了,在main主函数里设置3个任务分别2秒4秒5秒后开炮:
开始运行
结果在我的视频里面有
但这是线程不够安全,因为此时距离第一次任务还有很长时间,定时器就会循环取出任务看看时间到没到,所以需要在第一次取出任务看到时间没到就锁上,然后wait等待下次新任务插入进来看看是否比之前时间更短,再唤醒
这样就比较稳妥,不是太闹心所以先创建一个加锁对象
多个修改操作都要加锁()
下面的wait里面是下次任务到当前时间的间隔休眠等待插入新任务了唤醒,比较新任务的时间是否更小,
有wait就会有对应的notify操作
致此,才算实现了定时器全部,注意点有点多,总结一下哦:
1.先创建任务类里面有任务,时间还有实现比较任务的重写Comparable方法
2.定时器类里面一个扫描线程,判断是否最短时间的任务,一个安排任务的方法(当然还有后续加锁,循环处理)
3.主函数里实例定时器,调用安排任务函数方法来安排几个任务来跑