[toc]
定时器一般有三种表现形式:按固定周期定期执行、延迟一定时间后执行、指定时间执行。
基本操作新任务取消任务执行任务JDK原始定时器Timerer
Timer timer = newTimer();timer.scheduleAtFixedRate(newTimerTask(){ @Override public voidrun(){ // do something }}, 10000, 1000); // 10s 调度后的一个周期是 1s Publicic的定时任务 class Timer { private final TaskQueue queue = newTaskQueue(); private final TimerThread thread = newTimerThread(queue); public Timer(String name){ thread.setName(name); thread.start(); }}
- TaskQueueue是一个小顶堆。
queue[1]
始终是第一个执行任务。 - TimerThread 会定时轮询 TaskQueue 中的任务:
- 如果是堆顶的任务 deadline 到了,那么执行任务;
- 如果是周期性任务,则在执行完成后重新计算下一个任务 deadline,并再次放入小顶堆;
- 如果是单一执行的任务,执行结束后将从 TaskQueue 中删除。
public class DelayQueueTest { public static voidmain(String[] args) throws Exception { BlockingQueue<SampleTask> delayQueue = new DelayQueue<>(); long now = System.currentTimeMillis(); delayQueue.put(newSampleTask(now + 1000)); delayQueue.put(newSampleTask(now + 2000)); delayQueue.put(newSampleTask(now + 3000)); for(int i = 0; i <3; i++){ System.out.println(newDate(delayQueue.take().getTime())); } } static class SampleTask implements Delayed { long time; public SampleTask(long time){ this.time = time; } public long getTime(){ return time; } @Override public int compareTo(Delayed o){ return Long.compare(this.getDelay(TimeUnit.MILLISECONDS), o.getDelay(TimeUnit.MILLISECONDS)); } @Override public long getDelay(TimeUnit unit){ return unit.convert(time - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } }}
- DelayQueue 中间的每个对象都必须实现 Delayed 并重写界面 compareTo 和 getDelay 方法。
public class ScheduledExecutorServiceTest { public static voidmain(String[] args){ ScheduledExecutorService executor = Executors.newScheduledThreadPool(5); executor.scheduleAtFixedRate(() -> System.out.println("Hello World"), 1000, 2000, TimeUnit.MILLISECONDS); // 1s 延迟后开始执行任务,通常 2s 重复执行一次 }}
- 具有线程池异步处理任务的能力
时间轮算法的核心:轮询线程不再遍历任务,而是时间刻度。就像时钟上的指针一样,时间刻度是任务队列,指向任务队列。
假设每天24小时,刻度必须是24小时*
60*
60=86400。每次使用一次,都是浪费。
秒时间轮60个刻度;分级时间轮60个刻度;小时时间轮24小时
假设每天的 7:30:20 秒执行一次,秒时间轮20刻度,分级时间轮30刻度,小时时间轮7刻度:
- 二级指针指向20后,将此任务转移到分钟级指针;
- 将分钟级指针转移到30后,将此任务转移到小时级指针;
- 小时指针指向7后,执行任务,并将任务重新注册为秒指针。