ScheduledThreadPoolExecutor
执行延时任务和定时任务
原理
执行流程:
1)将任务包装成RunnableScheduledFuture接口的实现类;
2)将RunnableScheduledFuture任务放到延时队列,如果当前线程数量小于核心线程数,创建核心线程执行任务,如果当前线程数量等于0,创建一个空闲线程执行任务。从这里可以看出定时线程池的最大线程数量这个参数是无效的;
3)线程是ThreadPoolExecutor#Worker这个类,实现了Runnable接口,执行完当前任务后会不断从队列获取新的任务执行,这里从队列里面获取的任务当然就是RunnableScheduledFuture任务,它的唯一实现类是ScheduledFutureTask,它的run方法流程:
- 如果不是周期任务,直接执行任务设置结果;
- 如果是周期任务,成功执行完后设置下一次运行时间。就这样可以?当然不是,万一程序关闭了定时线程池,但还有周期任务没有完成怎么办?所以需要一个策略来判断当前定时线程池是否已经关闭,是否还需要继续执行周期任务,如果要执行,就把任务重新扔到队列中。
ScheduledExecutorService API
1)scheduleAtFixedRate:上一次任务的执行时间+周期period为下一次任务的执行时间;
2)scheduleWithFixedDelay:上一次任务执行完后延迟delay时间为下一次任务的执行时间;
那在代码层面怎么实现呢?
可以看出是通过提交任务的时候设置ScheduledFutureTask的period属性,period>0代表是scheduleAtFixedRate,period<0代表是scheduleWithFixedDelay。period!=0代表是周期任务。