一、概述

1、jdk的线程池和任务调用器分别由ExecutorService、ScheduledExecutorService定义,继承关系如下:

ThreadPoolExecutor:ExecutorService的实现类,其构造函数提供了灵活的参数配置,可构造多种类型的线程池,详细可参考JAVA进阶----ThreadPoolExecutor机制

ScheduledThreadPoolExecutor:ScheduledExecutorService的实现类,用于任务调度

2、spring task对定时任务的两个抽象:

  • TaskExecutor:与jdk中Executor相同,引入的目的是为定时任务的执行提供线程池的支持
  • TaskScheduler:对定时任务的抽象

继承关系如下:

任务执行器与调度器的实现类分别为ThreadPoolTaskExecutor、ThreadPoolTaskScheduler

TaskScheduler需要传入一个Runnable的任务做为参数,并指定需要周期执行的时间或者触发器(Trigger)。

spring定义了Trigger接口的实现类CronTrigger,支持使用cron表达式指定定时策略,使用如下:

scheduler.schedule(task, new CronTrigger("30 * * * * ?"));

二、定时任务

spring定时任务的使用和配置非常简单,支持xml配置和注解两个方式

1、XML配置方式

任务类

@Component
public class TestTask {
public void job() {
System.out.println("hello matt!");
}
}

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.1.xsd"> <context:component-scan base-package="cn.matt.schedule"/> <!-- 任务调度器-->
<task:scheduler id="myScheduler" pool-size="10"/> <!-- 任务配置-->
<task:scheduled-tasks scheduler="myScheduler">
<task:scheduled ref="testTask" method="job" cron="0/2 * * * * ?"/>
</task:scheduled-tasks>
</beans>

测试

public class TaskTest {
@Test
public void test() throws InterruptedException {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-context.xml");
TimeUnit.SECONDS.sleep(10);
}
}

2、注解方式

任务类

@Component
public class TestTask {
@Scheduled(cron = "0/2 * * * * ?")
public void job() {
System.out.println("hello matt!");
}
}

配置

<!-- 任务调度器-->
<task:scheduler id="myScheduler" pool-size="10"/> <!-- 开启任务注解-->
<task:annotation-driven scheduler="myScheduler"/>

测试代码与xml配置方式相同

补充说明:

  • 使用<task:executor>配置任务执行器,即实例化ThreadPoolTaskExecutor
  • 使用<task:scheduler>配置任务调度器,即实例化ThreadPoolTaskScheduler
  • 两种方式的任务调度器不指定时,默认会使用只有一个线程的调用器,关于配置的详细介绍和默认参数,可参考xsd文档 http://www.springframework.org/schema/task/spring-task-4.1.xsd

疑问:

有些项目同时指定任务执行器和调度器,如下:

<!-- 启用注解驱动的定时任务 -->
<task:annotation-driven scheduler="myScheduler" executor="myExecutor"/>
<!-- 配置定时任务的线程池 -->
<task:scheduler id="myScheduler" pool-size="10"/>
<task:executor id="myExecutor" pool-size="10" />

存在两个线程池,两者的关系是怎样的?执行器用的是哪个线程池?

经验证,定时任务执行时,使用的是任务调度器的线程池,任务执行器的设置对定时任务的执行没有影响,测试代码如下:

任务类

@Component
public class TestTask {
@Scheduled(cron = "0/5 * * * * ?")
public void job1() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(String.format("%s*******%s", sdf.format(new Date()), "job1"));
} @Scheduled(cron = "0/10 * * * * ?")
public void job2() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(String.format("%s*******%s", sdf.format(new Date()), "job2")); try {
TimeUnit.SECONDS.sleep(15);
} catch (InterruptedException e) {}
}
}

配置与疑问中相同

测试(测试时,通过改变线程池的大小进行验证)

public class TaskTest {
@Test
public void test() throws InterruptedException {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-context.xml");
TimeUnit.SECONDS.sleep(1000);
}
}

3、cron表达式

spring支持6个参数的cron表达式,格式如下:

{秒} {分} {时} {日期} {月} {星期}
  • 秒:必填项,允许的值范围是0-59,支持的特殊符号包括'-*/,',','表示特定的某一秒才会触发任务,'-'表示一段时间内会触发任务,'*'表示每一秒都会触发,'/'表示从哪一个时刻开始,每隔多长时间触发一次任务。
  • 分:必填项,允许的值范围是0-59,支持的特殊符号和秒一样,含义类推
  • 时:必填项,允许的值范围是0-23,支持的特殊符号和秒一样,含义类推
  • 日期:必填项,允许的值范围是1-31,支持的特殊符号相比秒多了?,表示与{星期}互斥,即意味着若明确指定{星期}触发,则表示{日期}无意义,以免引起冲突和混乱
  • 月:必填项,允许的值范围是1-12(JAN-DEC),支持的特殊符号与秒一样,含义类推
  • 星期:必填项,允许值范围是1~7 (SUN-SAT),1代表星期天(一星期的第一天),以此类推,7代表星期六,支持的符号相比秒多了?,表达的含义是与{日期}互斥,即意味着若明确指定{日期}触发,则表示{星期}无意义。

示例:

0 0 12 * * ?          每天中午12点触发
0 * 14 * * ? 每天下午2点到下午2:59期间的每1分钟触发
0 0/5 14 * * ? 每天下午2点到下午2:55期间的每5分钟触发
0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发

关于cron表达式的详细介绍可参考spring定时任务详解

三、异步调用

spring提供@Async注解,可很方便的实现异步调用,简单示例如下:

接口及实现类

public interface Hello {
void doSomething1();
void doSomething2();
}
@Component
public class HelloImpl implements Hello {
@Async
@Override
public void doSomething1() {
System.out.println(String.format("thread:%d **** doSomething1", Thread.currentThread().getId())); } @Async("myExecutor2")
@Override
public void doSomething2() {
System.out.println(String.format("thread:%d **** doSomething2", Thread.currentThread().getId()));
}
}

配置

<context:component-scan base-package="cn.matt.schedule"/>
<!-- 开启@Async注解支持 -->
<task:annotation-driven executor="myExecutor1"/>
<!-- 定义执行器 -->
<task:executor id="myExecutor1" pool-size="10" />
<task:executor id="myExecutor2" pool-size="10" />

测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-context.xml")
public class SpringTestBase {}
public class AsyncTest extends SpringTestBase {
@Autowired
private Hello hello; @Test
public void test() {
System.out.println(String.format("main thread:%d **** doSomething1", Thread.currentThread().getId())); hello.doSomething1();
hello.doSomething2();
}
} // 输出:
// main thread:1 **** doSomething1
// thread:20 **** doSomething2
// thread:19 **** doSomething1

说明:@Async默认使用<task:annotation-driven/>指定的执行器,当存在多个执行器时,可通过@Async的value属性单独指定

参考:

Spring任务调度之Spring-Task

spring定时任务详解(@Scheduled注解)

深入浅出Spring task定时任务

Spring异步任务处理,@Async的配置和使用

Spring中@Async

Spring 使用介绍(十二)—— Spring Task的更多相关文章

  1. spring boot / cloud (十二) 异常统一处理进阶

    spring boot / cloud (十二) 异常统一处理进阶 前言 在spring boot / cloud (二) 规范响应格式以及统一异常处理这篇博客中已经提到了使用@ExceptionHa ...

  2. Spring Cloud(十二):分布式链路跟踪 Sleuth 与 Zipkin【Finchley 版】

    Spring Cloud(十二):分布式链路跟踪 Sleuth 与 Zipkin[Finchley 版]  发表于 2018-04-24 |  随着业务发展,系统拆分导致系统调用链路愈发复杂一个前端请 ...

  3. thinkPHP 模板中的语法知识 详细介绍(十二)

    原文:thinkPHP 模板中的语法知识 详细介绍(十二) 本章节:介绍模板中的语法,详细的语法介绍 一.导入CSS和JS文件    ==>记住常量的是大写 1.css link .js  sc ...

  4. Spring Cloud第十二篇 | 消息总线Bus

    ​ ​本文是Spring Cloud专栏的第十二篇文章,了解前十一篇文章内容有助于更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring ...

  5. Spring Boot2 系列教程(三十二)Spring Boot 整合 Shiro

    在 Spring Boot 中做权限管理,一般来说,主流的方案是 Spring Security ,但是,仅仅从技术角度来说,也可以使用 Shiro. 今天松哥就来和大家聊聊 Spring Boot ...

  6. Spring Security(十二):5. Java Configuration

    General support for Java Configuration was added to Spring Framework in Spring 3.1. Since Spring Sec ...

  7. (转)Spring Boot 2 (十):Spring Boot 中的响应式编程和 WebFlux 入门

    http://www.ityouknow.com/springboot/2019/02/12/spring-boot-webflux.html Spring 5.0 中发布了重量级组件 Webflux ...

  8. Spring Boot 2 (十):Spring Boot 中的响应式编程和 WebFlux 入门

    Spring 5.0 中发布了重量级组件 Webflux,拉起了响应式编程的规模使用序幕. WebFlux 使用的场景是异步非阻塞的,使用 Webflux 作为系统解决方案,在大多数场景下可以提高系统 ...

  9. Spring学习(十)Spring知识点汇总

    一.基础概念 Q:Spring是什么? 定义:Spring是一个轻量级的IoC(控制反转)和AOP容器框架. 目的:用于简化企业应用程序的开发,使得开发者只需要关心业务需求. 常见的配置方式: 基于X ...

  10. Spring实战(十)Spring AOP应用——为方法引入新功能、为对象引入新方法

    切面最基本的元素是通知和切点,切点用于准确定位应该在什么地方应用切面的通知. 1.Spring借助AspectJ的切点表达式语言来定义Spring切面 在Spring中,要使用AspectJ的切点表达 ...

随机推荐

  1. c# WPF RichTextBox 文字颜色

    public MainWindow() { InitializeComponent(); Run run = new Run("This is my text"); run.For ...

  2. Project Tungsten:让Spark将硬件性能压榨到极限(转载)

    在之前的博文中,我们回顾和总结了2014年Spark在性能提升上所做的努力.本篇博文中,我们将为你介绍性能提升的下一阶段——Tungsten.在2014年,我们目睹了Spark缔造大规模排序的新世界纪 ...

  3. 【原创】分布式之elk日志架构的演进

    引言 好久没写分布式系列的文章了,最近刚好有个朋友给我留言,想看这方面的知识.其实这方面的知识,网上各种技术峰会的资料一抓一大把.博主也是凑合着写写.感觉自己也写不出什么新意,大家也凑合看看. 日志系 ...

  4. 学习用Node.js和Elasticsearch构建搜索引擎(3):使用curl命令操作elasticsearch

    使用Elasticsearch不免要提到curl工具,curl是利用URL语法在命令行方式下工作的开源文件传输工具.官网地址:https://curl.haxx.se/ 因为elasticsearch ...

  5. linus 下redis守护进程启动

    修改配置文件 sudo vim /usr/src/redis/redis.conf // 具体的安装目录不一样,以安装的时候为准 # 将daemonize 改为yes daemonize yes 重新 ...

  6. @RequestBody ajax 415 400

    使用springmvc和Ajax进行数据交互时使用标签@RequestBody时我报了这两个错,刚开始对springmvc的使用和注解有点迷,然后踩坑上了. 先说下怎么才会踩上去.首先@Request ...

  7. Python—反射

    反射 1 什么是反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它 ...

  8. [2019BUAA软工助教]第一次阅读 - 小结

    [2019BUAA软工助教]第一次阅读 - 小结 一.评分规则 总分 16 分,附加 2 分,共 18 分 markdown格式统一且正确 - 2分 不统一:扣 1 分 不正确:扣 1 分(例如使用代 ...

  9. 数据快速批量添加到Elasticsearch

    如何把数据快速批量添加到Elasticsearch中 问题来源 最近新做一个项目,有部分搜索比较频繁的数据,而且量级比较大,预计一两年时间很可能达到100G,项目要求不要存在数据库中,最终出来有两个方 ...

  10. Java面试题详解一:面向对象三大特性

    一,多态:1.面向对象四大基本特性:抽象,封装,继承,多态抽象,封装,继承是多态的基础.多态是抽象,封装,继承的表现.2.什么是多态不同类的对象对同一消息作出不同的响应叫做多态3.多态的作用简单来说: ...