新增AI编程课程,引领技术教育新趋势
public static void main(String[] args) { ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(3); scheduled.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println(); } }, 10, 30, TimeUnit.MILLISECONDS); }
1、概述
new一个线程池,等待队列是DelayedWorkQueue,将Runable放入队列中,到时间会被线程池取出执行
2、如何实现任务到时间被自动取出?
延时队列DelayedWorkQueue:
DelayedWorkQueue为ScheduledThreadPoolExecutor中的内部类(类似DelayQueue)
DelayedWorkQueue中的任务是按照延迟时间从短到长来进行排序的(插入时排序)
只有在延迟期满时才能从中提取元素,其列头是延迟期满后保存时间最长的Delayed元素
3、周期任务如何实现?
任务被取出来run之后,将time+period又放入DelayedWorkQueue队列
4、四个定时任务及区别:
(1)schedule(Callable callable, long delay, TimeUnit unit) :创建并执行在给定延迟后启用的 ScheduledFuture。
(2)schedule(Runnable command, long delay, TimeUnit unit) :创建并执行在给定延迟后启用的一次性操作。
(3)scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) :创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推。
(4)scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) :创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。
区别:
第三个方法(scheduleAtFixedRate)是周期固定,也就说它是不会受到这个延迟的影响的,每个线程的调度周期在初始化时就已经绝对了,是什么时候调度就是什么时候调度,它不会因为上一个线程的调度失效延迟而受到影响。
但是第四个方法(scheduleWithFixedDelay),则不一样,它是每个线程的调度间隔固定,也就是说第一个线程与第二线程之间间隔delay,第二个与第三个间隔delay,以此类推。如果第二线程推迟了那么后面所有的线程调度都会推迟。
scheduleAtFixedRate与scheduleWithFixedDelay区别原理:
任务被取出来run之后,将time+period又放入DelayedWorkQueue队列
细节一:构造ScheduledFutureTask时,scheduleAtFixedRate传入period(>0),scheduleWithFixedDelay传入-delay(<0)
细节二:setNextRunTime时,scheduleAtFixedRate.time=time+period;scheduleWithFixedDelay.time=now()+period
细节一:
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { if (command == null || unit == null) throw new NullPointerException(); if (period <= 0) throw new IllegalArgumentException(); ScheduledFutureTask<Void> sft = new ScheduledFutureTask<Void>(command, null, triggerTime(initialDelay, unit), unit.toNanos(period)); RunnableScheduledFuture<Void> t = decorateTask(command, sft); sft.outerTask = t; delayedExecute(t); return t; } public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { if (command == null || unit == null) throw new