Java并发(二十二):定时任务ScheduledThreadPoolExecutor

 需要在理解线程池原理的基础上学习定时任务:

    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

                    
                
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信