使用定义任务:

第一步:启用定时任务
第二步:配置定时器资源等
第三步:定义定时任务并指定触发规则

1)启动类启用定时任务

在springboot入口类上添加注解@EnableScheduling即可。

@SpringBootApplication(scanBasePackages = {})
@MapperScan("com.dx.jobmonitor.mapper")
@EnableScheduling
public class App {
private static final Logger logger = LoggerFactory.getLogger(App.class); public static void main(String[] args) {
logger.info("App start...");
SpringApplication.run(App.class, args);
}
}

2)配置定时任务资源等:

设置定时任务线程池大小:通过SchedulingConfigurer接口配置并行方式
当定时任务很多的时候,为了提高任务执行效率,可以采用并行方式执行定时任务,任务之间互不影响,只要实现SchedulingConfigurer接口就可以。

/**
* 配置定时任务<br>
* 1)当定时任务很多的时候,为了提高任务执行效率,可以采用并行方式执行定时任务,任务之间互不影响,只要实现SchedulingConfigurer接口就可以。<br>
* 2)这里指定用3个线程来并行处理
* **/
@Configuration
public class ScheduledConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.setScheduler(setTaskExecutors());
} @Bean(destroyMethod = "shutdown")
public Executor setTaskExecutors() {
return Executors.newScheduledThreadPool(3);
}
}

在并行执行的时候,创建线程池采用了newScheduledThreadPool这个线程池。
Executors框架中存在几种线程池的创建线程池的采用的队列是延迟队列:

  • newCachedThreadPool() ,
  • newFixedThreadPool(),
  • newSingleThreadExecutor(),
  • newScheduledThreadPool()。

newScheduledThreadPool() 线程池的特性是定时任务能够定时或者周期性的执行任务。

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

其中线程池核心线程数是自己设定的,最大线程数是最大值。阻塞队列是自定义的延迟队列:DelayedWorkQueue()

3)定义定时任务

定时任务1:

@Component
public class SchedulerTask {
private int count=0; @Scheduled(cron="*/6 * * * * ?")
private void process(){
System.out.println("this is scheduler task runing "+(count++));
}
}

定时任务2:

从application.yml中读取cron参数

@Component
public class Scheduler2Task {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); @Scheduled("jobs.scheduled.cron")
public void reportCurrentTime() {
System.out.println("现在时间:" + dateFormat.format(new Date()));
}
}

此时application.yml中配置信息如下:

jobs:
scheduled:
cron: 0/30 * * * * ?

参数说明:
  @Scheduled接受两种定时的设置:

  1. 一种是cornexpression。
  2. 一种是Rate/Delay表达式(毫秒值):
  • @Scheduled(fixedRate = 6000):上一次开始执行时间点后每隔6秒执行一次。
  • @Scheduled(fixedDelay = 6000):上一次执行完毕时间点之后6秒再执行。
  • @Scheduled(initialDelay=1000, fixedRate=6000):第一次延迟1秒后执行,之后按fixedRate的规则每6秒执行一次。

动态修改scheduled的cron参数:

动态修改定时任务cron参数时:

  • 1)不需要重启应用就可以动态的改变Cron表达式的值
  • 2)不能使用@Scheduled(cron = “${jobs.cron}”)实现
@Component
public class SpringDynamicCronTask implements SchedulingConfigurer {
private static final Logger logger = LoggerFactory.getLogger(SpringDynamicCronTask.class);
private static String cron = "0/5 * * * * ?"; @Autowired
private TaskDynamicCronService taskCronService; @Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.addTriggerTask(() -> {
// 任务逻辑
logger.error("dynamicCronTask is running...");
}, triggerContext -> {
// 任务触发,在这里可修改任务的执行周期,因为每次调度都会执行这里
// 1)这里可以修改为从数据读取cron
// cron=taskCronService.getCron();
CronTrigger cronTrigger = new CronTrigger(cron);
return cronTrigger.nextExecutionTime(triggerContext);
});
} /**
* 2) 供应用端调用动态修改cron参数方法
* @Controller
* @RequestMapping("/cron")")
* public class CronController{
* @Autowired
* private SpringDynamicCronTask cronTask;
*
* @PostMapping("/update")
* @ResponseBody
* public String update(String cron) {
* cronTask.setCron(cron);
* }
* }
*/
public void setCron(String cron) {
this.cron=cron;
}
}

动态设置cron参数常用方式包含两种:

1)动态查询并设置cron

定义CronTrigger时,从数据库中动态查询cron并设置

    @Autowired
private TaskDynamicCronService taskCronService; @Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.addTriggerTask(() -> {
// 任务逻辑
logger.error("dynamicCronTask is running...");
}, triggerContext -> {
cron=taskCronService.getCron();
CronTrigger cronTrigger = new CronTrigger(cron);
return cronTrigger.nextExecutionTime(triggerContext);
});
}

2)通过接口函数修改cron值

SpringDynamicCronTask 类,提供修改cron函数setCron()。

@Component
public class SpringDynamicCronTask implements SchedulingConfigurer {
private static final Logger logger = LoggerFactory.getLogger(SpringDynamicCronTask.class);
private static String cron = "0/5 * * * * ?";
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.addTriggerTask(() -> {
// 任务逻辑
logger.error("dynamicCronTask is running...");
}, triggerContext -> {
CronTrigger cronTrigger = new CronTrigger(cron);
return cronTrigger.nextExecutionTime(triggerContext);
});
} /**
* 供应用端调用动态修改cron参数方法
*/
public void setCron(String cron) {
this.cron=cron;
}
}

应用端调用:

@Controller
@RequestMapping("/cron")")
public class CronController{
@Autowired
private SpringDynamicCronTask cronTask; @PostMapping("/update")
@ResponseBody
public String update(String cron) {
cronTask.setCron(cron);
}
}

多定时任务管理

定义多定时任务管理类

class BatchTaskSchedule {
private ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
private ScheduledFuture<?> future;
private Integer key; public BatchTaskSchedule(Integer key) {
this.key = key;
} public void start() {
executor.setPoolSize(1);
executor.setThreadNamePrefix("taskExecutor-");
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
// 必须得先初始化,才能使用
executor.initialize();
future = executor.schedule(new Runnable() {
@Override
public void run() {
System.out.println("[" + Thread.currentThread().getName() + "-" + key + "]Hello "
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}, new CronTrigger("0/15 * * * * ?"));
} public void restart() {
// 先停止,在开启.
stop();
start();
} public void stop() {
if (future != null) {
future.cancel(true);
}
}
}

使用测试示例:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = { App.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CommonTest {
// 定时任务存储集合:当需要停止、重启任务时,可以从该集合中获取待操作任务。
private static Map<Integer, BatchTaskSchedule> taskBack = new HashMap<Integer, BatchTaskSchedule>(); @Test
public void test() {
for (int i = 0; i < 2; i++) {
// 创建定时任务
BatchTaskSchedule taskScheduled = new BatchTaskSchedule(i);
taskScheduled.start();
taskBack.put(i, taskScheduled);
} try {
Thread.sleep(1 * 60 * 1000);
// 停止掉某个任务
taskBack.get(0).stop();
Thread.sleep(1 * 60 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

SpringBoot(十三):springboot2.0.2定时任务的更多相关文章

  1. 【SpringBoot】SpringBoot2.0响应式编程

    ========================15.高级篇幅之SpringBoot2.0响应式编程 ================================ 1.SprinBoot2.x响应 ...

  2. 【SpringBoot】SpringBoot2.x整合定时任务和异步任务处理

    SpringBoot2.x整合定时任务和异步任务处理 一.项目环境 springboot2.x本身已经集成了定时任务模块和异步任务,可以直接使用 二.springboot常用定时任务配置 1.在启动类 ...

  3. Springboot:SpringBoot2.0整合WebSocket,实现后端数据实时推送!

    一.什么是WebSocket? B/S结构的软件项目中有时客户端需要实时的获得服务器消息,但默认HTTP协议只支持请求响应模式,这样做可以简化Web服务器,减少服务器的负担,加快响应速度,因为服务器不 ...

  4. SpringBoot2.0源码分析(一):SpringBoot简单分析

    SpringBoot2.0简单介绍:SpringBoot2.0应用(一):SpringBoot2.0简单介绍 本系列将从源码角度谈谈SpringBoot2.0. 先来看一个简单的例子 @SpringB ...

  5. SpringBoot2.0 基础案例(04):定时任务和异步任务的使用方式

    一.定时任务 1.基本概念 按照指定时间执行的程序. 2.使用场景 数据分析 数据清理 系统服务监控 二.同步和异步 1.基本概念 同步调用 程序按照代码顺序依次执行,每一行程序都必须等待上一行程序执 ...

  6. springboot学习入门简易版三---springboot2.0启动方式

    2.4使用@componentscan方式启动 2.4.1 @EnableAutoConfiguration 默认只扫描当前类 @EnableAutoConfiguration 默认只扫描当前类,如果 ...

  7. springboot学习入门简易版二---springboot2.0项目创建

    2 springboot项目创建(5) 环境要求:jdk1.8+ 项目结构: 2.1创建maven工程 Group id :com.springbootdemo Artifact id: spring ...

  8. SpringBoot(十一):springboot2.0.2下配置mybatis generator环境,并自定义字段/getter/settetr注释

    Mybatis Generator是供开发者在mybatis开发时,快速构建mapper xml,mapper类,model类的一个插件工具.它相对来说对开发者是有很大的帮助的,但是它也有不足之处,比 ...

  9. 零基础快速入门SpringBoot2.0教程 (三)

    一.SpringBoot Starter讲解 简介:介绍什么是SpringBoot Starter和主要作用 1.官网地址:https://docs.spring.io/spring-boot/doc ...

随机推荐

  1. jenkins(3): jenkins执行shell命令

    参考: https://www.cnblogs.com/reblue520/p/7146693.html 1. 执行 本地 shell命令或者脚本 是在一个构建中的  bulid 选项卡. 执行本地中 ...

  2. P1156 垃圾陷阱 DP

    题目描述 卡门――农夫约翰极其珍视的一条Holsteins奶牛――已经落了到“垃圾井”中.“垃圾井”是农夫们扔垃圾的地方,它的深度为D(2 \le D \le 100)D(2≤D≤100)英尺. 卡门 ...

  3. 记Ubuntu Mongodb 和 Mysql的安装与使用

    安装mongodb 参考链接 https://www.cnblogs.com/shileima/p/7823434.html https://blog.csdn.net/xlengji/article ...

  4. Ubuntu 硬盘分区只读,重新挂载为读写分区之后,文件依然创建出错

    原因: 分区只读,可能是windows没有正常关机,或者使用了混合休眠模式. 解决方案: sudo mount -o remount,rw /dev/sdaX 若重新挂载后,创建文件以及文件夹失败: ...

  5. Django项目中使用Redis

    Django项目中使用Redis DjangoRedis 1 redis Redis 是一个 key-value 存储系统,常用于缓存的存储.django-redis 基于 BSD 许可, 是一个使 ...

  6. 使用CCS调试基于AM335X的SPL、Uboot(原创)

    使用CCS调试基于AM335X的SPL.Uboot 一.开发环境 1.硬件平台:创龙AM3359核心板 2.SDK版本:ti-processor-sdk-linux-am335x-evm-03.00. ...

  7. react组件通信那些事儿

    父组件是调用组件的组件.现在看来,感觉父组件就是一个壳子,定义好壳子里面会有什么,而子组件是一个具体的实现,说明,会用到什么东西,如果有这些东西,会进行什么操作.总之,父组件是材料,有水和泥,子组件告 ...

  8. Centos 安装lnmp完整版

    1.使用putty或类似的SSH工具登录服务器: 登录后运行 screen -S lnmp 2.下载并安装LNMP一键安装包: 我是CentOS系统,所以运行: wget -c http://soft ...

  9. [ONTAK2015]Tasowanie

    [ONTAK2015]Tasowanie 题目大意: 给你两个长度分别为\(n(n\le2\times10^5)\)的序列\(A,B\),将\(A,B\)进行二路归并,使得最后得到的序列字典序最小.求 ...

  10. python 数据类型元组与字典内置方法

    1.元组 (1)元组是不可变的列表,能存多个值:如果多个值只有取得需求,没有改的需求,用元组最合理 (2)定义:在()内用逗号隔开,可以存任意类型的值 注意:当元组只有一个元素时,要在后面加逗号 # ...