Spring Boot 定时任务单线程和多线程
Spring Boot 的定时任务:
第一种:把参数配置到.properties文件中:
代码:
-
package com.accord.task;
-
-
import java.text.SimpleDateFormat;
-
import java.util.Date;
-
-
import org.springframework.scheduling.annotation.Scheduled;
-
import org.springframework.stereotype.Component;
-
-
/**
-
* 从配置文件加载任务信息
-
* @author 王久印
-
* 2018年3月1日
-
*/
-
@Component
-
public class ScheduledTask {
-
-
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
-
-
//@Scheduled(fixedDelayString = "${jobs.fixedDelay}")
-
@Scheduled(fixedDelayString = "2000")
-
public void getTask1() {
-
System.out.println("任务1,从配置文件加载任务信息,当前时间:" + dateFormat.format(new Date()));
-
}
-
-
@Scheduled(cron = "${jobs.cron}")
-
public void getTask2() {
-
System.out.println("任务2,从配置文件加载任务信息,当前时间:" + dateFormat.format(new Date()));
-
}
-
}
application.properties文件:
-
jobs.fixedDelay=5000
-
jobs.cron=0/5 * * * * ?
SpringBootCron2Application.java中:
-
package com.accord;
-
-
import org.springframework.boot.SpringApplication;
-
import org.springframework.boot.autoconfigure.SpringBootApplication;
-
import org.springframework.scheduling.annotation.EnableScheduling;
-
-
@SpringBootApplication
-
@EnableScheduling
-
public class SpringBootCron2Application {
-
public static void main(String[] args) {
-
SpringApplication.run(SpringBootCron2Application.class, args);
-
}
-
}
注:@EnableScheduling 这个一定要加上;否则,不会定时启动任务!
@Scheduled中的参数说明:
-
@Scheduled(fixedRate=2000):上一次开始执行时间点后2秒再次执行;
-
-
@Scheduled(fixedDelay=2000):上一次执行完毕时间点后2秒再次执行;
-
-
@Scheduled(initialDelay=1000, fixedDelay=2000):第一次延迟1秒执行,然后在上一次执行完毕时间点后2秒再次执行;
-
-
@Scheduled(cron="* * * * * ?"):按cron规则执行。
在线Cron表达式生成器:http://cron.qqe2.com/
第二种定时任务:单线程和多线程
1、创建定时任务:
-
package com.accord.task;
-
-
import org.slf4j.Logger;
-
import org.slf4j.LoggerFactory;
-
import org.springframework.scheduling.annotation.Scheduled;
-
import org.springframework.stereotype.Component;
-
-
/**
-
* 构建执行定时任务
-
* @author 王久印
-
* 2018年3月1日
-
* TODO
-
*/
-
@Component
-
public class ScheduledTask2 {
-
-
private Logger logger = LoggerFactory.getLogger(ScheduledTask2.class);
-
-
private int fixedDelayCount = 1;
-
private int fixedRateCount = 1;
-
private int initialDelayCount = 1;
-
private int cronCount = 1;
-
-
@Scheduled(fixedDelay = 5000) //fixedDelay = 5000表示当前方法执行完毕5000ms后,Spring scheduling会再次调用该方法
-
public void testFixDelay() {
-
logger.info("===fixedDelay: 第{}次执行方法", fixedDelayCount++);
-
}
-
-
@Scheduled(fixedRate = 5000) //fixedRate = 5000表示当前方法开始执行5000ms后,Spring scheduling会再次调用该方法
-
public void testFixedRate() {
-
logger.info("===fixedRate: 第{}次执行方法", fixedRateCount++);
-
}
-
-
@Scheduled(initialDelay = 1000, fixedRate = 5000) //initialDelay = 1000表示延迟1000ms执行第一次任务
-
public void testInitialDelay() {
-
logger.info("===initialDelay: 第{}次执行方法", initialDelayCount++);
-
}
-
-
@Scheduled(cron = "0 0/1 * * * ?") //cron接受cron表达式,根据cron表达式确定定时规则
-
public void testCron() {
-
logger.info("===initialDelay: 第{}次执行方法", cronCount++);
-
}
-
-
}
使用 @Scheduled来创建定时任务 这个注解用来标注一个定时任务方法。
通过看 @Scheduled源码可以看出它支持多种参数:
(1)cron:cron表达式,指定任务在特定时间执行;
(2)fixedDelay:表示上一次任务执行完成后多久再次执行,参数类型为long,单位ms;
(3)fixedDelayString:与fixedDelay含义一样,只是参数类型变为String;
(4)fixedRate:表示按一定的频率执行任务,参数类型为long,单位ms;
(5)fixedRateString: 与fixedRate的含义一样,只是将参数类型变为String;
(6)initialDelay:表示延迟多久再第一次执行任务,参数类型为long,单位ms;
(7)initialDelayString:与initialDelay的含义一样,只是将参数类型变为String;
(8)zone:时区,默认为当前时区,一般没有用到。
2、开启定时任务:
-
package com.accord;
-
-
import org.springframework.boot.SpringApplication;
-
import org.springframework.boot.autoconfigure.SpringBootApplication;
-
import org.springframework.scheduling.annotation.EnableScheduling;
-
-
@SpringBootApplication
-
@EnableScheduling
-
public class SpringBootCron2Application {
-
public static void main(String[] args) {
-
SpringApplication.run(SpringBootCron2Application.class, args);
-
}
-
}
注:这里的 @EnableScheduling 注解,它的作用是发现注解 @Scheduled的任务并由后台执行。没有它的话将无法执行定时任务。
引用官方文档原文:
@EnableScheduling ensures that a background task executor is created. Without it, nothing gets scheduled.
3、执行结果(单线程)
就完成了一个简单的定时任务模型,下面执行springBoot观察执行结果:
从控制台输入的结果中我们可以看出所有的定时任务都是在同一个线程池用同一个线程来处理的,那么我们如何来并发的处理各定时任务呢,请继续向下看。
4、多线程处理定时任务:
看到控制台输出的结果,所有的定时任务都是通过一个线程来处理的,我估计是在定时任务的配置中设定了一个SingleThreadScheduledExecutor,于是我看了源码,从ScheduledAnnotationBeanPostProcessor类开始一路找下去。果然,在ScheduledTaskRegistrar(定时任务注册类)中的ScheduleTasks中又这样一段判断:
-
if (this.taskScheduler == null) {
-
this.localExecutor = Executors.newSingleThreadScheduledExecutor();
-
this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
-
}
这就说明如果taskScheduler为空,那么就给定时任务做了一个单线程的线程池,正好在这个类中还有一个设置taskScheduler的方法:
-
public void setScheduler(Object scheduler) {
-
Assert.notNull(scheduler, "Scheduler object must not be null");
-
if (scheduler instanceof TaskScheduler) {
-
this.taskScheduler = (TaskScheduler) scheduler;
-
}
-
else if (scheduler instanceof ScheduledExecutorService) {
-
this.taskScheduler = new ConcurrentTaskScheduler(((ScheduledExecutorService) scheduler));
-
}
-
else {
-
throw new IllegalArgumentException("Unsupported scheduler type: " + scheduler.getClass());
-
}
-
}
这样问题就很简单了,我们只需用调用这个方法显式的设置一个ScheduledExecutorService就可以达到并发的效果了。我们要做的仅仅是实现SchedulingConfigurer接口,重写configureTasks方法就OK了;
-
package com.accord.task;
-
-
import org.springframework.context.annotation.Configuration;
-
import org.springframework.scheduling.annotation.SchedulingConfigurer;
-
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
-
-
import java.util.concurrent.Executors;
-
-
/**
-
* 多线程执行定时任务
-
* @author 王久印
-
* 2018年3月1日
-
*/
-
@Configuration
-
//所有的定时任务都放在一个线程池中,定时任务启动时使用不同都线程。
-
public class ScheduleConfig implements SchedulingConfigurer {
-
@Override
-
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
-
//设定一个长度10的定时任务线程池
-
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
-
}
-
}
5、执行结果(并发)
通过控制台输出的结果看出每个定时任务都是在通过不同的线程来处理了。
Spring Boot 定时任务单线程和多线程的更多相关文章
- Spring Boot定时任务应用实践
在Spring Boot中实现定时任务功能,可以通过Spring自带的定时任务调度,也可以通过集成经典开源组件Quartz实现任务调度. 一.Spring定时器 1.cron表达式方式 使用自带的定时 ...
- Spring Boot定时任务运行一段时间后自动关闭的解决办法
用Spring Boot默认支持的 Scheduler来运行定时任务,有时在服务器运行一段时间后会自动关闭.原因:Schedule默认是单线程运行定时任务的,即使是多个不同的定时任务,默认也是单线程运 ...
- spring boot 定时任务
定时任务实现方式 三种: 1) Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务. 最早的时候就是这样写定时任务的. 2) 开源的第三方框 ...
- spring boot.定时任务问题记录(TaskScheduler/ScheduledExecutorService异常)
一.背景 spring boot的定时任务非常简单,只需要在启动类中加上@EnableScheduling注解,然后在对应的方法上配置@Scheduled就可以了,系统会自动处理并按照Schedule ...
- (14)Spring Boot定时任务的使用【从零开始学Spring Boot】
本文介绍在 Spring Boot 中如何使用定时任务,使用非常简单,就不做过多说明了. com.kfit.base.scheduling.SchedulingConfig: package com. ...
- Spring Boot (十一): Spring Boot 定时任务
在实际的项目开发工作中,我们经常会遇到需要做一些定时任务的工作,那么,在 Spring Boot 中是如何实现的呢? 1. 添加依赖 在 pom.xml 文件中只需引入 spring-boot-sta ...
- Spring Boot 定时任务 @Scheduled
项目开发中经常需要执行一些定时任务,比如在每天凌晨,需要从 implala 数据库拉取产品功能活跃数据,分析处理后存入到 MySQL 数据库中.类似这样的需求还有许多,那么怎么去实现定时任务呢,有以下 ...
- Spring Boot 定时任务 Quartz 使用教程
Quartz是一个完全由java编写的开源作业调度框架,他使用非常简单.本章主要讲解 Quartz在Spring Boot 中的使用. 快速集成 Quartz 介绍 Quartz 几个主要技术点 Qu ...
- spring -boot定时任务 quartz 基于 MethodInvokingJobDetailFactoryBean 实现
spring 定时任务 quartz 基于 MethodInvokingJobDetailFactoryBean 实现 依赖包 如下 <dependencies> <depende ...
随机推荐
- oc30--id
// // Person.h #import <Foundation/Foundation.h> @interface Person : NSObject - (void)sleep; @ ...
- Struts2 中 result type=”json” 的参数解释
转自:http://wangquanhpu.iteye.com/blog/1461750 1, ignoreHierarchy 参数:表示是否忽略等级,也就是继承关系,比如:TestAction 继承 ...
- E20170905-mk
recursive adj. 回归的,递归的;
- 0522 json
一.概念 json依赖于js和xml,是一种数据交换格式,json对比xml的生成和处理要更加方便.因此在许多领域,json正逐步取代xml的使用. 二.使用 1.在JS当中 json在javascr ...
- 【DP悬线法】奶牛浴场
虽然还是悬线法,但是这道题可不能轻易地套模板了,而是要换一种思路,横着扫一遍,竖着扫一遍,时间复杂度依旧是O(n^2),然而空间复杂度有一定的优化 如果用原来的方法,显然时间空间都会炸(如果你想用ma ...
- 题解 UVA10587 【Mayor's posters】
先讲一下:dalao @lisuier 发布的前一篇题解严格来讲是有错误的 比如下一组数据: 1 3 1 10 1 4 7 10 显然答案是3,然而用lisuier dalao的程序做出来的答案是2( ...
- Ubuntu下搭建repo服务器(一): 配置gitosis
1. 说明 服务器端IP: 192.168.1.126,下文简称:A端: 客户端IP: 192.168.130.19,下文简称:B端: Android工程代号:17435. 2. 安装必要软件(A端) ...
- Safe Area Layout Guide before iOS 9.0
今天使用Xcode9.1重建项目,什么都没写运行报错:Safe Area Layout Guide before iOS 9.0!目前为止,不晓得原因,现记录解决方法:
- java编译器和java解释器、JVM
作用: JVM:JVM有自己完善的硬件架构,如处理器.堆栈(Stack).寄存器等,还具有相应的指令系统(字节码就是一种指令格式).JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需要生成 ...
- Hadoop学习笔记(一)Hadoop的单节点安装
要想深入学习Hadoop分布式文件系统,首先需要搭建Hadoop的实验环境,Hadoop有两种安装模式,即单节点集群模式安装(也称为伪分布式)和完全分布式模式安装,本节只介绍单节点模式的安装,参考官方 ...