定时任务系统

发布时间:2023-04-24 10:16:00

[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 中删除。
DelayedQueue
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 方法。
newScheduledThreadPool
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刻度:

  1. 二级指针指向20后,将此任务转移到分钟级指针;
  2. 将分钟级指针转移到30后,将此任务转移到小时级指针;
  3. 小时指针指向7后,执行任务,并将任务重新注册为秒指针。
上一篇 动态规划之机器人走路
下一篇 LeetCode面试题:最大矩形

文章素材均来源于网络,如有侵权,请联系管理员删除。

标签: Java教程Java基础Java编程技巧面试题Java面试题