小议时序调度Timer和Quartz
本文不是用来讲授入门手把手ABC小例子的,算是自己这段时间对Timer和Quartz使用心得的总结吧,后续如果有更深的认识会不断更新的。
言归正传,想实现定时调度,最简单的方法是使用Timer
还是先给个使用范例:
long PERIOD = 60*1000;//一分钟Timer timer = new Timer("sure's timer");timer.schedule(new TimerTask() {@Overridepublic void run() {if(!doSomething()){timer.cancel();}}}, 0, PERIOD);
public class Timer { private TaskQueue queue = new TaskQueue(); private TimerThread thread = new TimerThread(queue);}
class TimerThread extends Thread { private TaskQueue queue;//任务队列 public void run() { try { mainLoop(); } finally { // Someone killed this Thread, behave as if Timer cancelled synchronized(queue) { newTasksMayBeScheduled = false; queue.clear(); } } }private void mainLoop() { while (true) { try { TimerTask task; boolean taskFired; synchronized(queue) { // 如果队列为空则等待 while (queue.isEmpty() && newTasksMayBeScheduled) queue.wait(); if (queue.isEmpty()) break; // 如果不再会非空,则跳出 // 队列非空,则取第一个任务执行 long currentTime, executionTime; task = queue.getMin();//取第一个任务 synchronized(task.lock) { if (task.state == TimerTask.CANCELLED) { queue.removeMin(); continue; // 任务已取消则继续取任务 } currentTime = System.currentTimeMillis();//当前时间 executionTime = task.nextExecutionTime;//任务将开始执行的时间 if (taskFired = (executionTime<=currentTime)) { if (task.period == 0) { queue.removeMin(); task.state = TimerTask.EXECUTED;//已执行完成 } else { //重复执行(***) queue.rescheduleMin( task.period<0 ? currentTime - task.period : executionTime + task.period); } } } if (!taskFired) // 还没到时间,则等到执行开始时间 queue.wait(executionTime - currentTime); } if (taskFired) // 执行 task.run(); } catch(InterruptedException e) { } } }}
class TaskQueue { private TimerTask[] queue = new TimerTask[128]; ...}
public abstract class TimerTask implements Runnable { final Object lock = new Object();//锁 public abstract void run(); public boolean cancel() { synchronized(lock) { boolean result = (state == SCHEDULED); state = CANCELLED; return result; } }}
public void schedule(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); }private void sched(TimerTask task, long time, long period) { if (time < 0) throw new IllegalArgumentException("Illegal execution time."); synchronized(queue) { if (!thread.newTasksMayBeScheduled) throw new IllegalStateException("Timer already cancelled."); synchronized(task.lock) { if (task.state != TimerTask.VIRGIN) throw new IllegalStateException( "Task already scheduled or cancelled"); task.nextExecutionTime = time;//设置该任务的开始时间 task.period = period;//设置该任务的周期 task.state = TimerTask.SCHEDULED;//将该任务的状态设为SCHEDULED } queue.add(task);//将该任务加入到任务队列中 if (queue.getMin() == task) queue.notify();//当列队的第一个任务是该任务时,唤醒 } }