踩坑系列之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 Spring
【注解】Spring AOP 面向切面编程之@Around的详细用法
【注解】Spring AOP 面向切面编程之@Around的详细用法
3089 0
|
消息中间件 Java 物联网
一文搞懂MQTT,如何在SpringBoot中使用MQTT实现消息的订阅和发布
之前介绍了RabbitMQ以及如何在SpringBoot项目中整合使用RabbitMQ,看过的朋友都说写的比较详细,希望再总结一下目前比较流行的MQTT。所以接下来,就来介绍什么MQTT?它在IoT中有着怎样的作用?如何在项目中使用MQTT?
18984 63
一文搞懂MQTT,如何在SpringBoot中使用MQTT实现消息的订阅和发布
|
前端开发 网络协议 Dubbo
超详细Netty入门,看这篇就够了!
本文主要讲述Netty框架的一些特性以及重要组件,希望看完之后能对Netty框架有一个比较直观的感受,希望能帮助读者快速入门Netty,减少一些弯路。
91448 32
超详细Netty入门,看这篇就够了!
|
缓存 Java 调度
使用scheduleAtFixedRate进行定时任务调度
使用scheduleAtFixedRate进行定时任务调度
|
10月前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
9008 5
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
Java Spring
SpringBoot: 启动Banner在线生成工具
SpringBoot: 启动Banner在线生成工具
34558 1
SpringBoot: 启动Banner在线生成工具
|
XML Java 测试技术
Graalvm 替代 JVM 真的可以带来巨大的性能优势吗?
介绍 Spring Boot有助于轻松开发独立的、可用于生产的 Spring 应用程序。它对 Spring 平台和第三方库采用固执己见的方法:以最少的配置简化设置过程。优势: 易于使用:Spring Boot 简化了独立 Spring 应用程序的创建,无需复杂的配置。 嵌入式服务器:它允许直接嵌入 Tomcat、Jetty 或 Undertow 等服务器,从而无需单独部署 WAR 文件。 Starter 依赖项:Spring Boot 提供预配置的“starter”依赖项,降低了构建配置的复杂性。 自动配置:Spring Boot 自动配置 Spring 和第三方库,最大限度地减少手动设置工
|
Java 编译器 Spring
面试突击78:@Autowired 和 @Resource 有什么区别?
面试突击78:@Autowired 和 @Resource 有什么区别?
15166 6
|
缓存 安全 Java
使用ScheduledExecutorService进行任务调度
使用ScheduledExecutorService进行任务调度