SpringBoot定时任务可以用于周期性重复工作的编写,其应用简单,能满足绝大多数需求。在Java中实现定时任务主要有三种实现形式:一是使用JDK 自带的 Timer,二是使用第三方组件 Quartz,三是使用 Spring Task。 前两个不是我们今天讨论的重点,暂且不提,今天只讲一下spring定时任务的三个应用场景:一是最简单的使用注解配置定时任务;二是通过配置文件开关定时任务;三是通过服务动态开启开启关闭定时任务。

1. @Scheduled注解

使用注解方式进行开发是最简单的应用方式,一般只需要两步即可实现:在需要定时启动的服务上添加@Scheduled(initialDelay=1000, fixedDelay = 2000)注解;在启动类上添加启动定时任务的注解@EnableScheduling

@Component
public class ScheduledTask {@Scheduled(initialDelay=1000, fixedDelay = 2000)public void task1() {System.out.println("延迟1000毫秒后执行,任务执行完2000毫秒之后执行!");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}@Scheduled(initialDelay=1000, fixedRate = 2000)public void task2() {System.out.println("延迟1000毫秒后执行,之后每2000毫秒执行一次!");}@Scheduled(cron = "*/2 * * * * ?")public void task3() {System.out.println("每2秒执行一次!");}
}

启动类上配置注解

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

2.配置文件动态配置定时任务启动

很多时候我们开发的定时任务可能需要按照现场情况来去启动或者关闭,这就想通过配置文件来进行定时任务的启动和关闭,这个时候可以借助Condition 和ScheduledAnnotationBeanPostProcessor 来实现。在上面代码的基础上,我们需要去掉启动类上的@EnableScheduling注解,然后在配置文件中添加我们的自定义配置:

enable:scheduling: false

添加SchedulerCondition获取配置文件配置

public class SchedulerCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {return Boolean.valueOf(context.getEnvironment().getProperty("enable.scheduling"));}
}

添加Scheduler

@Configuration
public class Scheduler {@Conditional(SchedulerCondition.class)@Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {return new ScheduledAnnotationBeanPostProcessor();}
}

然后再去启动项目时,程序就会根据我们的自定义配置来进行启动关闭定时任务。

3.服务启动中动态开启关闭定时任务

上面的两种实现形式其配置粒度都是整个服务的,然而,有时候服务中可能存在不同的定时任务,其开启关闭的要求不同,所以就需要对单个定时任务进行开启关闭,还要保证服务正常运行,这就需要使用另外的设计了。

package com.lordum.threadpoolpractice.controller;import com.lordum.threadpoolpractice.config.AppConfiguration;
import com.lordum.threadpoolpractice.tasks.MyRunnable1;
import com.lordum.threadpoolpractice.tasks.MyRunnable2;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Date;
import java.util.concurrent.ScheduledFuture;@Slf4j
@RestController
@Api("定时任务")
@RequestMapping("/quartz/task")
public class DynamicTaskController {@Autowiredprivate AppConfiguration appConfiguration;@Autowiredprivate ThreadPoolTaskScheduler threadPoolTaskScheduler;private ScheduledFuture<?> future1;private ScheduledFuture<?> future2;@Beanpublic ThreadPoolTaskScheduler threadPoolTaskScheduler() {return new ThreadPoolTaskScheduler();}@PostMapping("/startCron1")@ApiOperation("开始定时任务1")public ResponseEntity<String> startCron1() {if (future1 != null) {return ResponseEntity.ok("定时任务1已经启动,请不要重复启动");}future1 = threadPoolTaskScheduler.schedule(new MyRunnable1("url"), triggerContext ->new CronTrigger(appConfiguration.getCorn1()).nextExecutionTime(triggerContext));System.out.println("DynamicTask.startCron1()");return ResponseEntity.ok().build();}@PostMapping("/stopCron1")@ApiOperation("关闭定时任务1")public ResponseEntity<String> stopCron1() {if (future1 != null) {future1.cancel(true);}System.out.println("DynamicTask.stopCron1()");future1 = null;return ResponseEntity.ok().build();}@PostMapping("/startCron2")@ApiOperation("开始定时任务2")public ResponseEntity<String> startCron2() {if (future2 != null) {return ResponseEntity.ok("定时任务2已经启动,请不要重复启动");}future2 = threadPoolTaskScheduler.schedule(new MyRunnable2(), triggerContext ->new CronTrigger(appConfiguration.getCorn2()).nextExecutionTime(triggerContext));System.out.println("DynamicTask.startCron2()");return ResponseEntity.ok().build();}@PostMapping("/stopCron2")@ApiOperation("关闭定时任务2")public ResponseEntity<String> stopCron2() {if (future2 != null) {future2.cancel(true);}System.out.println("DynamicTask.stopCron2()");future2 = null;return ResponseEntity.ok().build();}}

这里面的MyRunnable1和MyRunnable2是我们要执行的定时任务,需要实现Runnable接口

package com.lordum.threadpoolpractice.tasks;import lombok.AllArgsConstructor;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Callable;@AllArgsConstructor
public class MyRunnable1 implements Runnable {private String testParam;@Overridepublic void run() {System.out.println("first DynamicTask,获取到参数:[" +testParam+ "]-"  + Thread.currentThread().getName() + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));}
}
package com.lordum.threadpoolpractice.tasks;import java.text.SimpleDateFormat;
import java.util.Date;public class MyRunnable2 implements Runnable {@Overridepublic void run() {System.out.println("second DynamicTask," + Thread.currentThread().getName() + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));}
}

Controller类中添加了配置了,需要读取配置文件中的corn配置。

package com.lordum.threadpoolpractice.config;import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Data
@Component
@ConfigurationProperties(prefix = "app")
@EqualsAndHashCode(callSuper = false)
public class AppConfiguration {private String corn1;private String corn2;
}

自定义配置:

app:corn1: 0/2 * * * * ?corn2: 0/5 * * * * ?

4.Cron表达式

Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域。每一个域代表一个含义,Cron有如下两种语法格式:

Seconds Minutes Hours DayofMonth Month DayofWeek Year
Seconds Minutes Hours DayofMonth Month DayofWeek

corn从左到右(用空格隔开):秒 分 小时 月份中的日期 月份 星期中的日期 年份

eg:
*/2 * * * * ? 表示每2秒执行一次!
0 0 2 1 * ? * 表示在每月的1日的凌晨2点调度任务
0 15 10 ? * MON-FRI 表示周一到周五每天上午10:15执行作业
0 15 10 ? 6L 2002-2006 表示2002-2006年的每个月的最后一个星期五上午10:15执行作业

SpringBoot定时任务简单应用相关推荐

  1. SpringBoot定时任务实现的两种方式介绍

    今天给大家介绍SpringBoot定时任务实现的几种方式,希望对大家能有所帮助! 1.SpringTask 用法 框架介绍:SpringTask是Spring自带的轻量级定时任务工具,相比于Quart ...

  2. 开关配置springboot定时任务

    题外话 这是我第五篇原创文章,计划写定时任务内容,想想只要打开自己的有道云笔记,复制粘贴,整理排版一下就能轻松搞定了,这样做有意义吗?自己写文章的价值点是什么呢?考虑了很长时间,主要希望做到一下几点: ...

  3. SpringBoot定时任务(@Scheduled)说明

    转载文章:http://blog.csdn.net/loongshawn/article/details/50663393 1. 定时任务实现方式 定时任务实现方式: Java自带的java.util ...

  4. SpringBoot定时任务 - 集成quartz实现定时任务(单实例和分布式两种方式)

    最为常用定时任务框架是Quartz,并且Spring也集成了Quartz的框架,Quartz不仅支持单实例方式还支持分布式方式.本文主要介绍Quartz,基础的Quartz的集成案例本,以及实现基于数 ...

  5. SpringBoot 定时任务的实现

    介绍两种实现方式:配置实现和读取数据库定时任务配置实现. 配置实现比较简单.直接撸代码: package com; import java.util.Properties; import org.ap ...

  6. LTS简介以及与SpringBoot的简单集成

    LTS简介以及与SpringBoot的简单集成 一 什么是LTS 关于定时任务,虽然Spring提供了基于注解@EnableScheduling @Scheduled的实现方式.其实现是通过线程池Sc ...

  7. SpringBoot定时任务升级篇(动态添加修改删除定时任务)

    (1)思路说明: (a)首先这里我们需要重新认识一个类ThreadPoolTaskScheduler:线程池任务调度类,能够开启线程池进行任务调度. (b)ThreadPoolTaskSchedule ...

  8. Java 实现 Springboot 定时任务(每隔一段时间自动执行一次)

    Java实现非Web项目的Springboot定时任务(每3秒自动执行一次) 前言 一.新建Java Springboot项目 二.示例代码 运行效果 总结 前言 运行非Web的Springboot项 ...

  9. celery定时任务简单使用

    celery介绍 Celery 是一个强大的分布式任务队列,它可以让任务的执行完全脱离主程序,甚至可以被分配到其他主机上运行.我们通常使用它来实现异步任务( async task )和定时任务( cr ...

最新文章

  1. 顺风详解Nginx系列—Ngx中的变量
  2. .NET 4.0有一个新的GAC,为什么?
  3. arp_annouce=2详解
  4. 用python阐释工作量证明(proof of work)
  5. myeclipse如何换一个漂亮的主题
  6. 【Linux】free命令查询服务器内存信息
  7. 【C语言】数据类型转换的问题
  8. 计算机进程调度论文,计算机操作系统小论文Linux进程调度.doc
  9. php评论倒序 zblog_zblogPHP评论链接加密并美化跳转的完美方法
  10. chrome自定义背景_Android Chrome自定义标签
  11. select2多选框无法手动排序问题[转载]
  12. Ugly Number II
  13. 系统背景描述_【通用博世丨智能广播系统】新都芳华微马公园
  14. 【ZOJ 1964】【尺取】Bound Found【暑期 No.3】
  15. 图解设计模式 - Adapter 模式
  16. OFFICE 图标异常解决办法
  17. 传奇微端需要下载客户端吗?传奇微端架设教程,微端配置教程
  18. 函数声明应该写在什么位置?main函数里面还是前面?(都可以,只要在调用语句的前面即可)
  19. 您的计算机无法正常启动,3种简单的方法 修复错误 ‘您的电脑无法正常启动’...
  20. 《结构思考力》- 书摘整理

热门文章

  1. 公交线路客流预测——手把手教你玩数据(一)
  2. hdu4411(费用流)
  3. 网络上的优美感人句子
  4. MATLAB 按组聚类绘图gscatter
  5. 雷诺手表怎么看型号?rarone型号查询的方法
  6. Android自我进阶总纲—善始者实繁,然克终者盖寡。
  7. 鲲鹏计算产业的典型应用
  8. #SORA#etcd研究
  9. 【ToolBar】Android ToolBar之完全解析
  10. 微信小程序跳转报错errMsg: “navigateTo:fail webview count limit exceed“