踩坑系列之scheduleWithFixedDelay 和 scheduleAtFixedRate

简介:

定时任务和延时任务的理解

  • ScheduledExecutorService#scheduleAtFixedRate() 指的是“以固定的频率”执行,period(周期)指的是两次成功执行之间的时间。上一个任务开始的时间计时,一个period后,检测上一个任务是否执行完毕,如果上一个任务执行完毕,则当前任务立即执行,如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行。
  • ScheduledExecutorService#scheduleWithFixedDelay() 指的是“以固定的延时”执行,delay(延时)指的是一次执行终止和下一次执行开始之间的延迟。

示例

scheduleAtFixedRate

public static void main(String[] args) {
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat(
            "my-test-pool-%d").build();
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1, threadFactory);
        Date startTime = new Date();
        System.out.println("startTime: " + startTime.toString());
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            System.out.println("beginTime: " + new Date().toString());
            try {
                Thread.sleep(5 * 1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("endTime: " + new Date().toString());
        }, 2, 3, TimeUnit.SECONDS);
    }

输出:

startTime: Sun Feb 16 11:17:09 CST 2020
beginTime: Sun Feb 16 11:17:11 CST 2020
endTime: Sun Feb 16 11:17:16 CST 2020
beginTime: Sun Feb 16 11:17:16 CST 2020
endTime: Sun Feb 16 11:17:21 CST 2020
beginTime: Sun Feb 16 11:17:21 CST 2020
endTime: Sun Feb 16 11:17:26 CST 2020
beginTime: Sun Feb 16 11:17:26 CST 2020
endTime: Sun Feb 16 11:17:31 CST 2020
beginTime: Sun Feb 16 11:17:31 CST 2020
endTime: Sun Feb 16 11:17:36 CST 2020
beginTime: Sun Feb 16 11:17:36 CST 2020

当前任务执行时间大于等于间隔时间,任务执行后立即执行下一次任务。相当于连续执行了。

scheduleWithFixedDelay

public static void main(String[] args) {
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat(
            "my-test-pool-%d").build();
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1, threadFactory);
        Date startTime = new Date();
        System.out.println("startTime: " + startTime.toString());
        scheduledExecutorService.scheduleWithFixedDelay(() -> {
            System.out.println("beginTime: " + new Date().toString());
            try {
                Thread.sleep(5 * 1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("endTime: " + new Date().toString());
        }, 2, 3, TimeUnit.SECONDS);
    }

输出:

startTime: Sun Feb 16 11:27:26 CST 2020
beginTime: Sun Feb 16 11:27:28 CST 2020
endTime: Sun Feb 16 11:27:33 CST 2020
beginTime: Sun Feb 16 11:27:36 CST 2020
endTime: Sun Feb 16 11:27:41 CST 2020
beginTime: Sun Feb 16 11:27:44 CST 2020
endTime: Sun Feb 16 11:27:49 CST 2020
beginTime: Sun Feb 16 11:27:52 CST 2020

每当上次任务执行完毕后,间隔一段时间执行。不管当前任务执行时间大于、等于还是小于间隔时间,执行效果都是一样的。

常见的“坑”

关于定时线程池(定时任务scheduleAtFixedRate和延时任务scheduleWithFixedDelay),好多人认为设置好频率(比如1Min),它会按照这个间隔按部就班的工作。但是,如果其中一次调度任务卡住的话,不仅这次调度失败,而且整个线程池也会停在这次调度上。

示例

如果run方法中抛出异常,而又没有捕获,会导致整个定时任务卡住。建议在整个run方法中使用try...catch...fianlly...处理。

public static void main(String[] args) {
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat(
            "my-test-pool-%d").build();
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1, threadFactory);
        Date startTime = new Date();
        System.out.println("startTime: " + startTime.toString());
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            System.out.println("beginTime: " + new Date().toString());
            try {
                Thread.sleep(5 * 1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("endTime: " + new Date().toString());
            throw new NullPointerException();
        }, 2, 3, TimeUnit.SECONDS);
    }

image

目录
相关文章
|
Java Maven Windows
java 获取视频第一帧 | Java工具类
java 获取视频第一帧 | Java工具类
java 获取视频第一帧 | Java工具类
|
架构师 NoSQL Java
【案例实战】SpringBoot3.x自定义封装starter实战
【案例实战】SpringBoot3.x自定义封装starter实战
【案例实战】SpringBoot3.x自定义封装starter实战
|
Android开发 Shell
Android模拟点击的四种方式
导论 在Android中模拟一个点击事件有三种方式是通过模拟MotionEvent来实现;一种是通过ADB来实现;一种是通过Instrumentation测试框架来实现 第一种:模拟MotionEvent 通用方法如下: private void setSimulateClick(View ...
8965 0
|
Java 应用服务中间件 Shell
tomcat启动报错 java.util.zip.ZipException: invalid CEN header (bad signature)
war包部署到tomcat里,启动时报错: Caused by: org.apache.catalina.LifecycleException: Failed to initialize component [org.
14847 0
|
11月前
|
消息中间件 Java Shell
RocketMQ集群部署与快速入门全解密:从原理到实战,万字干货吃透消息中间件
本文详解Apache RocketMQ核心概念、多Master多Slave集群部署及Java实战,涵盖NameServer、Broker配置、消息收发、事务消息与故障排查,助你掌握分布式消息系统搭建与应用。
1705 3
|
缓存 Java 调度
使用scheduleAtFixedRate进行定时任务调度
使用scheduleAtFixedRate进行定时任务调度
|
安全 Java 调度
Java中简单定时任务的实现
在 Java 中实现定时任务有多种方式,每种方式的原理和适用场景不同。`java.util.Timer` 和 `TimerTask` 通过单线程执行任务,适合简单场景;`ScheduledExecutorService` 基于线程池,支持多线程并发,更加灵活和健壮;三种方式各有优劣,开发者可根据需求选择合适的方案。
|
Java API 调度
ThreadPoolTaskScheduler轻量级多线程定时任务框架
面对一些小的功能需求点,如果需要非常灵活的进行处理定时任务处理,但是又因为你的需求需要使用到页面进行定时任务配置,显然使用Spring注解定时任务,无法满足你,这时你想到了xxl-job 或者 quezy等定时任务框架,但是过于繁琐,可能成本较大。那么本文将要解决你的问题
3698 0
|
安全 Java 测试技术
最佳实践:通义灵码生成单元测试,让单测更简单
本文首先讲述了什么是单元测试、单元测试的价值、一个好的单元测试所具备的原则,进而引入如何去编写一个好的单元测试,通义灵码是如何快速生成单元测试的。

热门文章

最新文章