很多时候我们都需要为系统建立一个定时任务来帮我们做一些事情,SpringBoot 已经帮我们实现好了一个,我们只需要直接使用即可,当然你也可以不用 SpringBoot 自带的定时任务,整合 Quartz 很多时候也是一个不错的选择。

Spring Schedule 实现定时任务

我们只需要 SpringBoot 项目最基本的依赖即可,所以这里就不贴配置文件了。

1. 创建一个 scheduled task

我们使用 @Scheduled 注解就能很方便地创建一个定时任务,下面的代码中涵盖了 @Scheduled的常见用法,包括:固定速率执行、固定延迟执行、初始延迟执行、使用 Cron 表达式执行定时任务。

Cron 表达式: 主要用于定时作业(定时任务)系统定义执行时间或执行频率的表达式,非常厉害,你可以通过 Cron 表达式进行设置定时任务每天或者每个月什么时候执行等等操作。

推荐一个在线Cron表达式生成器:http://cron.qqe2.com/

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit; /**
* @author shuang.kou
*/
@Component
public class ScheduledTasks {
private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); /**
* fixedRate:固定速率执行。每5秒执行一次。
*/
@Scheduled(fixedRate = 5000)
public void reportCurrentTimeWithFixedRate() {
log.info("Current Thread : {}", Thread.currentThread().getName());
log.info("Fixed Rate Task : The time is now {}", dateFormat.format(new Date()));
} /**
* fixedDelay:固定延迟执行。距离上一次调用成功后2秒才执。
*/
@Scheduled(fixedDelay = 2000)
public void reportCurrentTimeWithFixedDelay() {
try {
TimeUnit.SECONDS.sleep(3);
log.info("Fixed Delay Task : The time is now {}", dateFormat.format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
} /**
* initialDelay:初始延迟。任务的第一次执行将延迟5秒,然后将以5秒的固定间隔执行。
*/
@Scheduled(initialDelay = 5000, fixedRate = 5000)
public void reportCurrentTimeWithInitialDelay() {
log.info("Fixed Rate Task with Initial Delay : The time is now {}", dateFormat.format(new Date()));
} /**
* cron:使用Cron表达式。 每分钟的1,2秒运行
*/
@Scheduled(cron = "1-2 * * * * ? ")
public void reportCurrentTimeWithCronExpression() {
log.info("Cron Expression: The time is now {}", dateFormat.format(new Date()));
}
}

关于 fixedRate 这里其实有个坑,假如我们有这样一种情况:我们某个方法的定时器设定的固定速率是每5秒执行一次。这个方法现在要执行下面四个任务,四个任务的耗时是:6 s、6s、 2s、 3s,请问这些任务默认情况下(单线程)将如何被执行?

我们写一段简单的程序验证:

    private static final Logger log = LoggerFactory.getLogger(AsyncScheduledTasks.class);
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
private List<Integer> index = Arrays.asList(6, 6, 2, 3);
int i = 0;
@Scheduled(fixedRate = 5000)
public void reportCurrentTimeWithFixedRate() {
if (i == 0) {
log.info("Start time is {}", dateFormat.format(new Date()));
}
if (i < 5) {
try {
TimeUnit.SECONDS.sleep(index.get(i));
log.info("Fixed Rate Task : The time is now {}", dateFormat.format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}

运行程序输出如下:

Start time is 20:58:33
Fixed Rate Task : The time is now 20:58:39
Fixed Rate Task : The time is now 20:58:45
Fixed Rate Task : The time is now 20:58:47
Fixed Rate Task : The time is now 20:58:51

看下面的运行任务示意图应该很好理解了。

如果我们将这个方法改为并行运行,运行结果就截然不同了。

2. 启动类上加上@EnableScheduling注解

在 SpringBoot 中我们只需要在启动类上加上@EnableScheduling便可以启动定时任务了。

@SpringBootApplication
@EnableScheduling
public class DemoApplication { public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

3. 自定义线程池执行 scheduled task

默认情况下,@Scheduled任务都在Spring创建的大小为1的默认线程池中执行,你可以通过在加了@Scheduled注解的方法里加上下面这段代码来验证。

logger.info("Current Thread : {}", Thread.currentThread().getName());

你会发现加上上面这段代码的定时任务,每次运行都会输出:

Current Thread : scheduling-1

如果我们需要自定义线程池执行话只需要新加一个实现SchedulingConfigurer接口的 configureTasks 的类即可,这个类需要加上 @Configuration 注解。

@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
private final int POOL_SIZE = 10; @Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); threadPoolTaskScheduler.setPoolSize(POOL_SIZE);
threadPoolTaskScheduler.setThreadNamePrefix("my-scheduled-task-pool-");
threadPoolTaskScheduler.initialize(); scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
}
}

通过上面的验证的方式输出当前线程的名字会改变。

4. @EnableAsync 和 @Async 使定时任务并行执行

如果你想要你的代码并行执行的话,还可以通过@EnableAsync 和 @Async这两个注解实现

@Component
@EnableAsync
public class AsyncScheduledTasks {
private static final Logger log = LoggerFactory.getLogger(AsyncScheduledTasks.class);
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); /**
* fixedDelay:固定延迟执行。距离上一次调用成功后2秒才执。
*/
//@Async
@Scheduled(fixedDelay = 2000)
public void reportCurrentTimeWithFixedDelay() {
try {
TimeUnit.SECONDS.sleep(3);
log.info("Fixed Delay Task : The time is now {}", dateFormat.format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

运行程序输出如下,reportCurrentTimeWithFixedDelay() 方法会每5秒执行一次,因为我们说过了@Scheduled任务都在Spring创建的大小为1的默认线程池中执行。

Current Thread : scheduling-1
Fixed Delay Task : The time is now 14:24:23
Current Thread : scheduling-1
Fixed Delay Task : The time is now 14:24:28
Current Thread : scheduling-1
Fixed Delay Task : The time is now 14:24:33

reportCurrentTimeWithFixedDelay() 方法上加上 @Async 注解后输出如下,reportCurrentTimeWithFixedDelay() 方法会每 2 秒执行一次。

Current Thread : task-1
Fixed Delay Task : The time is now 14:27:32
Current Thread : task-2
Fixed Delay Task : The time is now 14:27:34
Current Thread : task-3
Fixed Delay Task : The time is now 14:27:36

Spring Schedule 实现定时任务的更多相关文章

  1. Spring Schedule实现定时任务

    applicationContext.xml 1. 增加配置 <!-- 开启定时任务 --> <task:annotation-driven /> <!-- 开启注解 - ...

  2. SpringBoot之旅 -- 定时任务两种(Spring Schedule 与 Quartz 整合 )实现

    相关文章 Spring Boot 相关文章目录 前言 最近在项目中使用到定时任务,之前一直都是使用Quartz 来实现,最近看Spring 基础发现其实Spring 提供 Spring Schedul ...

  3. spring schedule定时任务(一):注解的方式

    我所知道的java定时任务的几种常用方式: 1.spring schedule注解的方式: 2.spring schedule配置文件的方式: 3.java类继承TimerTask: 第一种方式的实现 ...

  4. SpringBoot系列:Spring Boot定时任务Spring Schedule

    Spring Schedule是Spring提供的定时任务框架,相较于Quartz,Schedule更加简单易用,在中小型应用中,对于大部分需求,Schedule都可以胜任. 一.Spring Sch ...

  5. (转)Java任务调度框架Quartz入门教程指南(二) 使用job、trigger、schedule调用定时任务

    http://blog.csdn.net/zixiao217/article/details/53044890 读完第一节,我们已经对Quartz有了一个大体的认识,它可以定时帮我们执行一些处理程序, ...

  6. 【Spring Boot】定时任务

    [Spring Boot]定时任务 测试用业务Service package com.example.schedule.service; import org.springframework.ster ...

  7. 任务调度(02)Spring Schedule

    任务调度(02)Spring Schedule [toc] Spring 3.0 提供两种任务调度方式:一是定时任务调度:二是异步任务调度.这两种任务调度方式都是基于 JUC 实现的,是一种非常轻量级 ...

  8. Spring动态添加定时任务

    Spring动态添加定时任务 一.背景 二.需求和实现思路 1.能够动态的添加一个定时任务. 2.能够取消定时任务的执行. 3.动态的修改任务执行的时间. 4.获取定时任务执行的异常 三.代码实现 四 ...

  9. spring多线程与定时任务

    本篇主要描述一下spring的多线程的使用与定时任务的使用. 1.spring多线程任务的使用 spring通过任务执行器TaskExecutor来实现多线程与并发编程.通常使用ThreadPoolT ...

随机推荐

  1. SpringCloud全家桶学习之路由网关----Zuul(六)

    一.Zuul概述 (1)Zuul是什么? Zuul包含了对请求的路由和过滤的两个最主要的功能,其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础:而过滤功能则负责对请求的 ...

  2. SpringCloud全家桶学习之服务注册与发现及Eureka高可用集群搭建(二)

    一.Eureka服务注册与发现 (1)Eureka是什么? Eureka是NetFlix的一个子模块,也是核心模块之一.Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故 ...

  3. php与js的false类型

    php除了下面列出来的情况是false  其余情况都可以看成true 包括NaN 和 空资源 整数 0 浮点数 0.0 空字符串 '' 或者'0' false 空数组 NULL类型 空标生成Simpl ...

  4. Spring 事务管理的使用

    Spring提供了2种事务管理 编程式的 声明式的(重点):包括xml方式.注解方式(推荐) 基于转账的demo dao层 新建包com.chy.dao,包下新建接口AccountDao.实现类Acc ...

  5. Steam 游戏 《Sudoku Universe(数独宇宙)》、《Sudoku Killer(数独杀手)》、《Sudoku Jigsaw(数独拼图)》数字位置解析 ---------C# 数独程序解析(2020年寒假小目标11)

    日期:2020.02.11 博客期:151 星期二 今天,准备肝一个 C# 的数独读写工具(汇编语言也在努力学习命令方法中...),这三个游戏我早就买下了,一直放在 Steam 库里积灰,看着它的成就 ...

  6. numpy.bincount正确理解

    今天看了个方法,numpy.bincount首先官网文档: numpy.bincount numpy.bincount(x, weights=None, minlength=0) Count numb ...

  7. python学习笔记:字符串格式化

    % 格式化方法 "我的名字是 %s, 我的年龄是 %d" % (name, age) 常用格式:%[(name)][flags][width].[precision]typecod ...

  8. idea整合scala

    scala依赖java环境,首先下载jdk1.8 64位 1.windows安装scala环境 下载scala环境,执行 进入doc窗口输入scala -version查看scala版本号,出现版本号 ...

  9. cf854B Maxim Buys an Apartment

    Maxim Buys an Apartment #include <iostream> #define int long long using namespace std; int n,k ...

  10. MQTT Web Toolkit - MQTT 在线客户端及服务器测试

    MQTT Web Toolkit 是 EMQ 最近开源的一款 MQTT (WebSocket) 测试工具,支持线上 (tools.emqx.io) 访问使用.该工具采用了聊天界面形式,简化了页面操作逻 ...