一、使用Java原生的Timer和TimerTask
(实质上是Object.wait()).
这一机制的实现主要有四部分组成,Timer,TimerTask,TimerThread,TimerQueue
Timer,TimerTask两部分是面相用户的,
TimerThread,TimerQueue两部分是面向系统。
Timer - 添加等操作的接口
添加和删除任务的接口,其实相当于一个包装类,主要靠它所持有的来实现定时机制。
固定延时
比较注重执行的间隔时间
每隔五分钟进行一次网络请求
设置 delay = 0,period=10.
若因为延时,第一次执行时间为 15
第二次执行时间在没有延时的情况下,将会是25
public void schedule(TimerTask task, Date firstTime, long period) {
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, firstTime.getTime(), -period);
}
固定速率
比较注重任务的执行周期
适用于 - 每个整点进行一次报时
设置 delay = 0,period=10.
若因为延时,第一次执行时间为 15
第二次执行时间在没有延时的情况下,将会是20
public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, System.currentTimeMillis()+delay, period);
}
TimerTask - 任务代码,要做的事
是任务的具体实现,implements Runnable接口。
持有一些属性,用来
period 可以设置为负值,也可以设置为正值。
/**
*
* Period in milliseconds for repeating tasks. A positive value indicates
* fixed-rate execution. A negative value indicates fixed-delay execution.
* A value of 0 indicates a non-repeating task.
*/
long period = 0;
TimerQueue - 任务的持有者
一般用户是看不到她,任务的持有者。添加任务都是添加到这里。
- 在用户添加任务时,他负责对队列中的任务按时间的先后进行排序。
- 在重复任务执行完以后,负责对该任务进行重新添加以及时间计算。
TimerThread - 任务的执行者
任务的执行者,一个不停循环的线程。
在任务队列中没有任务时,进行等待。
在用户取消timer 时候,线程结束。
1-1 当任务队列中有任务时,选取第一个任务,计算执行时间差值。
任务执行时间-当前时间=时间差值
2-1 时间差值为负,说明已经过了该任务的执行时间,立刻执行
2-2 时间差值为正,还没有到达该任务的执行时间,调用object. wait() 方法,休眠时间差值。重新取出第一个任务,此时时间差值不为正,效果类似于上一幕。
3-1 执行该任务,若任务是单次执行的,设置任务状态为已执行,否则重新设置任务的执行。
- 因为以上的定时执行机制,所以无法保证任务准时执行。
- 因为是单线程对应单队列,所以若前一个任务耗费了很大的时间,最后一个任务的执行时间与预先设置的时间可能会差值很大。
二、使用handler来实现 (消息机制)
Handler
Message
MessageQueue