16 ScheduledThreadPoolExecutor定时任务详解,schedule,scheduleWithFixedDelay,scheduleAtFixedRate避坑指南

ScheduledThreadPoolExecutor 延迟或定时任务执行线程池

ScheduledThreadPoolExecutor主要用来在给定的延迟之后运行任务,或者定期执行任务。

ScheduledThreadPoolExecutor的功能与Timer类似,但 ScheduledThreadPoolExecutor功能更强大、更灵活。

Timer对应的是单个后台线程,而ScheduledThreadPoolExecutor可以在构造函数中指定多个对应的后台线程数。

ScheduledThreadPoolExecutor还提供了非常灵活的API,用于执行任务。

其任务的执行策略主要分为两大类:

  • 在一定延迟之后只执行一次某个任务;
  • 在一定延迟之后周期性的执行某个任务。
//延迟delay时间后,执行command任务一次
public ScheduledFuture<?> schedule(Runnable command,long delay,TimeUnit unit) {}
//延迟delay时间后,执行callable任务一次,返回值为V
public <V> ScheduledFuture<V> schedule(Callable<V> callable,long delay,TimeUnit unit) {}
//延迟initialDelay时间后开始第1次执行,预计第n次执任务的时间等于首次开始执行时间+period*(n-1)(n>0,每次加1),预计第n次执任务时间>=上次结束时间,则按预计第n次执任务时间执行任务,反之则按上次结束时间实行任务
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit) {}
//延迟initialDelay时间后,第一次执行command任务,上次执行command任务终止后,延迟delay时间,再次执行command任务
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit) {}

public class ScheduledTest {
    static int i=1;
    public static void main(String[] args) {
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
        System.out.println("开始执行定时任务:" + new Date());
        //延迟initialDelay时间后,第一次执行command任务,如果上一次任务执行完毕后,其执行时间大于等于period,则选择在上个任务开始时间+period的倍数之后执行下个任务,如果上次任务执行完毕后,其执行时间小于period,则选择在上个任务开始时间+period之后执行下个任务。
        executor.scheduleAtFixedRate(()->{
            System.out.println("第"+i+"次 beginTime:" + new Date());
            try {
                if (i<5){
                    Thread.sleep(i*1000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("第"+i+"次 endTime:" + new Date());
            i++;
        },1,2, TimeUnit.SECONDS);
    }
}
   
//执行结果:
//开始执行任务定时任务 和 第一次执行任务之间 间隔initialDelay时间  这里设置1秒
开始执行定时任务:Sun Aug 06 11:39:55 CST 20231次 beginTime:Sun Aug 06 11:39:56 CST 20231次 endTime:Sun Aug 06 11:39:57 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处1倍)之后的时间(11:39:58)。预计下次开始执行时间>=本次结束时间(11:39:57),则下次执行开始时间为预计下次开始执行时间(11:39:58)  2次 beginTime:Sun Aug 06 11:39:58 CST 20232次 endTime:Sun Aug 06 11:40:00 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处2倍)之后的时间(11:40:00)。预计下次开始执行时间>=本次结束时间(11:40:00),则下次执行开始时间为预计下次开始执行时间(11:40:00)3次 beginTime:Sun Aug 06 11:40:00 CST 20233次 endTime:Sun Aug 06 11:40:03 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处3倍)之后的时间(11:40:02)。预计下次开始执行时间<本次结束时间(11:40:03),则下次执行开始时间为本次结束时间(11:40:03)4次 beginTime:Sun Aug 06 11:40:03 CST 20234次 endTime:Sun Aug 06 11:40:07 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处4倍)之后的时间(11:40:04)。预计下次开始执行时间<本次结束时间(11:40:07),则下次执行开始时间为本次结束时间(11:40:07)   5次 beginTime:Sun Aug 06 11:40:07 CST 20235次 endTime:Sun Aug 06 11:40:07 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处5倍)之后的时间(11:40:06)。预计下次开始执行时间<本次结束时间(11:40:07),则下次执行开始时间为本次结束时间(11:40:07)       6次 beginTime:Sun Aug 06 11:40:07 CST 20236次 endTime:Sun Aug 06 11:40:07 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处6倍)之后的时间(11:40:08)。预计下次开始执行时间>=本次结束时间(11:40:07),则下次执行开始时间为预计下次开始执行时间(11:40:08)7次 beginTime:Sun Aug 06 11:40:08 CST 20237次 endTime:Sun Aug 06 11:40:08 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处7倍)之后的时间(11:40:10)。预计下次开始执行时间>=本次结束时间(11:40:08),则下次执行开始时间为预计下次开始执行时间(11:40:10)8次 beginTime:Sun Aug 06 11:40:10 CST 20238次 endTime:Sun Aug 06 11:40:10 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处8倍)之后的时间(11:40:12)。预计下次开始执行时间>=本次结束时间(11:40:10),则下次执行开始时间为预计下次开始执行时间(11:40:12)9次 beginTime:Sun Aug 06 11:40:12 CST 20239次 endTime:Sun Aug 06 11:40:12 CST 2023
//预计下次开始执行时间为首次开始执行时间(11:39:56)+period(2秒)*的倍数(此处9倍)之后的时间(11:40:14)。预计下次开始执行时间>=本次结束时间(11:40:12),则下次执行开始时间为预计下次开始执行时间(11:40:14)10次 beginTime:Sun Aug 06 11:40:14 CST 202310次 endTime:Sun Aug 06 11:40:14 CST 2023

Process finished with exit code -1

public class ScheduledTest {
    static int i=1;
    public static void main(String[] args) {
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2);  
        延迟initialDelay时间后,第一次执行command任务,上次执行command任务终止后,延迟delay时间,再次执行command任务
        executor.scheduleWithFixedDelay(()->{
            System.out.println(new Date());
            try {
                Thread.sleep(i*1000);
                i++;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },1,5, TimeUnit.SECONDS);
    }
}
// 执行结果
Sun Aug 06 10:48:53 CST 2023
Sun Aug 06 10:48:59 CST 2023
Sun Aug 06 10:49:06 CST 2023
Sun Aug 06 10:49:14 CST 2023
Sun Aug 06 10:49:23 CST 2023
Sun Aug 06 10:49:33 CST 2023
Sun Aug 06 10:49:44 CST 2023
public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue());
}
public ScheduledThreadPoolExecutor(int corePoolSize,
                                   ThreadFactory threadFactory) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue(), threadFactory);
}

public ScheduledThreadPoolExecutor(int corePoolSize,
                                   RejectedExecutionHandler handler) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue(), handler);
}

public ScheduledThreadPoolExecutor(int corePoolSize,
                                   ThreadFactory threadFactory,
                                   RejectedExecutionHandler handler) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue(), threadFactory, handler);
}


public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EngineerForSoul

你的鼓励是我孜孜不倦的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值