一:定时器
定时器就是"闹钟"效果
指定一个任务(Runnable),并且指定一个时间(比如3000ms),此时这个任务不会立即执行,而是在时间到达之后,再去执行.
起到定时执行/延时执行的效果
定时器在日常开发中,是非常重要的基础组件.
比如:短信验证,验证码是有时效的,5min,
这样的效果就可以使用定时器,发送短信验证码的时候,生成验证码,保存起来,设定定时器,就会在5分钟之后,执行一个任务,删除刚才的那个验证码.
再比如:wait(),join(),带有阻塞时间,也可以理解成有定时器,定时器在达到时间之后自动唤醒.
正因为定时器非常重要,未来实际开发中,甚至会把定时器功能单独封装成服务器,供整个分布式系统来使用.
二:Timer
Java标准库的定时器.
public class Demo1 {
public static void main(String[] args) {
Timer timer=new Timer();
timer.schedule(new TimerTask() {
//TimerTask 相当于Runnable
@Override
public void run() {
System.out.println("hello 5000");
}
},5000);//5000ms后执行
/**
* delay :表示"多长时间后执行,以当前执行"schedule"的时刻为基准
* 继续等delay时间之后再去进一步的执行
*
*/
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("hello 1000");
}
},1000);//1000ms后执行
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("hello 3000");
}
},3000);//3000ms后执行
}
}
发现线程并没有结束,这是因为Timer内部包含了前台线程.阻止了进程结.
三:定时器的模拟实现
3.1:需求分析:
(1)能够延时执行任务/指定时间执行任务.
(2)能够管理多个任务
3.2:需要执行的任务
一个完整的任务,既要包含任务本身内容,也要 包含任务执行时间.
定义一个类,表示一个任务,有两个属性:任务内容和任务执行时间.
当前 自己定义的任务中,要保存执行任务的绝对时间(时间戳),为了后续线程执行的时候,可以方便的判定,该任务是否能够执行,如果是保存delay,随着时间的推移,还要更新delay,比较麻烦.
3.3:管理任务的方式
管理任务,最直观的方式就是通过List,通过遍历List集合中的元素,来判断是否执行当前线程,但如果这里的元素有很多,后续用来执行任务的线程,就需要不停循环的扫描这里的每个任务,分别判断是否要执行,效率比较低.
可以把这些任务通过优先级队列保存起来,按照时间作为优先级的先后的标准,就可以做到,队首元素就是时间最靠前的任务.
优先级队列,引用类型需要知道比较方法,此时需实现Compable接口.
扫描线程只需要关注队首元素即可(时间最靠前的任务,没到执行时间,剩下的 元素就更没到执行时间).
3.4:负责执行任务的线程
在构造方法中,创建一个线程,用线程来执行队列中的元素.
class MyTimerTask{
private Runnable runnable;//任务
private