常见方案
- 单机:JDK的Timer、ScheduledThreadPoolExecutor,及Spring的@Scheduled;
- 分布式:Quartz;
JDK Timer
实现原理: 每个定时器实例绑定一个消费线程和任务队列,业务线程提交定时任务到任务队列,任务按照下次执行时间在队列中排序;消费线程每次从队首获取任务,查看是否超过执行时间点,超过则立马执行,否则await等待,如果是周期任务则再计算下次执行时间点,将任务插入队列,如下图所示:
优缺点: Timer为单线程模式,当某个任务很耗时时容易导致后续待执行的任务收到影响,并且如果任务执行异常也没有捕获,导致线程终止运行,因此除了一些特别简单的场景,生产环境不建议使用;
ScheduledThreadPoolExecutor
实现原理:每个定时器实例绑定一个消费线程池和任务队列,业务线程提交定时任务到任务队列,任务按照下次执行时间在队列中排序;消费线程池中的线程每次从队首获取任务,查看是否超过执行时间点,超过则立马执行,否则await等待,如果是周期任务则再计算下次执行时间点,将任务插入队列;
- 创建实例:配置线程池和创建任务队列;
- 提交任务:按照下次执行时间插入队列;