第11章 任务调度

任务调度由三部分组成:

  • 任务:需要在特定时间运行或定期运行的业务逻辑块;
  • 触发器:指定任务应该执行的条件;
  • 调度程序:根据来自触发器的信息执行任务;

11.2 Spring中的任务调度

在Spring应用程序中可以使用多种方法触发任务的执行。

一种方法是通过已存在于应用程序部署环境中的调度系统从外部触发作业。作业触发可以通过向Spring应用程序发送RESTful-WS请求并让Spring的MVC控制器触发任务来完成。

另一种方法是在Spring中使用任务调度支持。Spring在任务调度方面提供了三个选项:

  • 支持JDK定时器
  • 与Quartz集成
  • Spring自己的Spring TaskScheduler抽象

11.2.1 Spring TaskScheduler抽象介绍

Spring的TaskScheduler抽象主要有三个参与者:

  • 任务:可以指定为任何Spring bean的方法
  • Trigger接口:org.springframework.scheduling.Trigger
  • TaskScheduler接口:org.springframework.scheduling.TaskScheduler

11.2.2 研究示例任务

使用XML配置和Java配置结合的方式配置简单任务调度:

// ----XML配置--------//
<?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:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd"> <task:scheduler id="timeScheduler" pool-size="10"/> <task:scheduled-tasks>
<task:scheduled ref="testSchedulerConfig" method="sayTime" fixed-delay="3000"/>
</task:scheduled-tasks> </beans> // ----Java配置与测试--------//
@Slf4j
@Configuration
@Component("testSchedulerConfig")
@ImportResource("classpath:chapter11/ac_task_test.xml")
public class TestSchedulerConfig { public void sayTime() {
log.error("======" + new Date().toLocaleString());
} public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(TestSchedulerConfig.class); }
}

11.2.3 使用注解进行任务调度

Spring提供了@Scheduled注解来使用Spring的TaskScheduler抽象。要使用注解支持,可以在XML配置中使用<task:annotation-driver>标记或在配置类上使用@EnableScheduling注解。

@Slf4j
@Configuration
@EnableScheduling
public class TestAnnoSchedulerConfig { @Scheduled(fixedRate = 1000)
public void sayTime() {
log.error("======" + new Date().toLocaleString());
} public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(TestAnnoSchedulerConfig.class); }
}

任务调度原理:

org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor

这个类既是后置处理器,又是事件监听器,监听ContextRefreshedEvent事件;

refresh()--finishBeanFactoryInitialization()中调用后置处理器方法进行配置;在refresh()--finishRefresh();中通过事件监听的方式开始执行任务调度;

11.2.4 Spring中异步任务的执行

Spring使用@Async注解来异步执行任务。

// ----------定义异步任务-------------//
@Slf4j
@Service("asyncService")
public class AsyncServiceImpl implements AsyncService {
@Async
@Override
public void asyncTask() {
log.error("AsyncServiceImpl...asyncTask...111"); try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
} log.error("AsyncServiceImpl...asyncTask...222");
} @Async
@Override
public Future<String> asyncWithReturn(String name) {
log.error("AsyncServiceImpl...asyncWithReturn...111==" + name); try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.error("AsyncServiceImpl...asyncWithReturn...222==" + name);
return new AsyncResult<>("Hello: " + name);
}
} // ----------定义Java配置-------------//
@Configuration
@EnableAsync
@Import({AsyncServiceImpl.class})
public class AsyncConfig { } // ----------测试程序-------------//
@Slf4j
public class AsyncTaskDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AsyncConfig.class);
AsyncService asyncService = ctx.getBean("asyncService", AsyncService.class); for (int i = 0; i < 5; i++) {
asyncService.asyncTask();
} Future<String> result1 = asyncService.asyncWithReturn("John Mayer");
Future<String> result2 = asyncService.asyncWithReturn("Eric Clapton");
Future<String> result3 = asyncService.asyncWithReturn("BB King"); log.error("result1 == " + result1.get());
log.error("result2 == " + result2.get());
log.error("result3 == " + result3.get());
}
}

原理:基于后置处理器org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor

11.3 Spring中任务的执行

Spring通过TaskExecutor接口执行任务的抽象。TaskExecutor执行由Java Runnable实现表示的任务。Spring提供了很多适合不同需求的TaskExecutor实现。

  • SimpleAsyncTaskExecutor:在每次调用时创建新线程,不重用现有的线程。
  • SyncTaskExecutor:不会异步执行,调用发生在调用线程中。
  • SimpleThreadPoolTaskExecutor:Quartz的SimpleThreadPool的子类,但需要Quartz和非Quartz组件之间共享线程池时使用。
  • ThreadPoolTaskExecutor:TaskExecutor的一种实现,提供了通过bean属性配置java.util.concurrent.ThreadPoolExecutor并将其作为Spring TaskExecutor公开的功能。
// --------定义执行任务----------- //
@Slf4j
@Component
public class TaskToExecute {
@Autowired
private TaskExecutor taskExecutor; public void executeTask() {
for (int i = 0; i < 10; i++) {
taskExecutor.execute(() -> log.info("Hello from thread: " + Thread.currentThread().getName()));
}
}
} // --------定义Java配置类----------- //
@Configuration
@EnableAsync
@Import({TaskToExecute.class})
public class TaskConfig {
@Bean
public TaskExecutor taskExecutor() {
return new SimpleAsyncTaskExecutor();
}
} // --------测试程序----------- //
public class TaskExecutorDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(TaskConfig.class); TaskToExecute taskToExecute = ctx.getBean(TaskToExecute.class);
taskToExecute.executeTask(); ctx.close();
}
}

通过Async注解异步执行时,默认使用的是SimpleAsyncTaskExecutor,如果没有定义类型为TaskExecutor的bean或名称为taskExecutor的类型为Executor的bean。

20191105 《Spring5高级编程》笔记-第11章的更多相关文章

  1. C#高级编程笔记之第二章:核心C#

    变量的初始化和作用域 C#的预定义数据类型 流控制 枚举 名称空间 预处理命令 C#编程的推荐规则和约定 变量的初始化和作用域 初始化 C#有两个方法可以一确保变量在使用前进行了初始化: 变量是字段, ...

  2. C#高级编程9 第11章 Linq

    Linq 1.Linq概述 列表和实体 准备数据: public class Championship { public int Year { get; set; } public string Fi ...

  3. C#高级编程笔记之第一章:.NET体系结构

    1.1 C#与.NET的关系 C#不能孤立地使用,必须与.NET Framework一起使用一起考虑. (1)C#的体系结构和方法论反映了.NET基础方法论. (2)多数情况下,C#的特定语言功能取决 ...

  4. 20191105 《Spring5高级编程》笔记-【目录】

    背景 开始时间:2019/09/18 21:30 Spring5高级编程 版次:2019-01-01(第5版) Spring5最新版本:5.1.9 CURRENT GA 官方文档 Spring Fra ...

  5. 读《C#高级编程》第1章问题

    读<C#高级编程>第1章 .Net机构体系笔记 网红的话:爸爸说我将来会是一个牛逼的程序员,因为我有一个梦,虽然脑壳笨但是做事情很能坚持. 本章主要是了解.Net的结构,都是一些概念,并没 ...

  6. Android高级编程笔记(四)深入探讨Activity(转)

    在应用程序中至少包含一个用来处理应用程序的主UI功能的主界面屏幕.这个主界面一般由多个Fragment组成,并由一组次要Activity支持.要在屏幕之间切换,就必须要启动一个新的Activity.一 ...

  7. C#高级编程9 第18章 部署

    C#高级编程9 第18章 部署 使用 XCopy 进行部署 本主题演示如何通过将应用程序文件从一台计算机复制到另一台计算机来部署应用程序. 1.将项目中生成的程序集复制到目标计算机,生成的程序集位于项 ...

  8. C#高级编程9 第17章 使用VS2013-C#特性

    C#高级编程9 第17章 使用VS2013 编辑定位到 如果默认勾选了这项,请去掉勾选,因为勾选之后解决方案的目录会根据当前文件选中. 可以设置项目并行生成数 版本控制软件设置 所有文本编辑器行号显示 ...

  9. C#高级编程9 第16章 错误和异常

    C#高级编程9 第16章 错误和异常 了解这章可以学会如何处理系统异常以及错误信息. System.Exception类是.NET运行库抛出的异常,可以继承它定义自己的异常类. try块代码包含的代码 ...

随机推荐

  1. 028-实现阿里云ESC多FLAT网络

    实现类似于阿里云ECS的网络结构,其效果为云主机拥有两块和两个不同的网络,一个网络是用于用于和外网连接,一个用于内网通信,但宿主机上至少有两个网卡,整体配置如下:1.在wmare里给宿主机添加一块网卡 ...

  2. Codeforces 916 二进制1数目构造(阅读理解) 最小生成树1-N路径质数构造

    A #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #def ...

  3. 网络流 最大流SAPkuangbin模板

    hdu 1532 求1~n的最大流 #include<stdio.h> #include<string.h> #include<algorithm> #includ ...

  4. Maven Pom文件标签详解

    <span style="padding:0px; margin:0px"><project xmlns="http://maven.apache.or ...

  5. 前端之CSS:CSS选择器

    前端之css样式(选择器)... 一.css概述 CSS是Cascading Style Sheets的简称,中文称为层叠样式表,对html标签的渲染和布局 CSS 规则由两个主要的部分构成:选择器, ...

  6. CSS3制作太极图以及用JS实现旋转太极图

     太极图可以理解为一个一半黑一半白的半圆,上面放置着两个圆形,一个黑色边框白色芯,一个白色边框黑色芯. 1.实现黑白各半的圆形. .box{ width:200px;height:200px; bor ...

  7. @PathVariable注解使用

    @PathVariable是spring3.0的一个新功能:接收请求路径中占位符的值 语法: @PathVariable("xxx")通过 @PathVariable 可以将URL ...

  8. Ubuntu 16.04下使用docker部署Redis主从复制

    (以下docker相关的命令,需要在root用户环境下或通过sudo提升权限来进行操作.) 1.拉取Redis镜像到本地 docker pull redis 2. 准备Redis主从配置文件 Redi ...

  9. 【bzoj2502】清理雪道

    题目描述: 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升 ...

  10. [CSP-S模拟测试]:小P的生成树(数学+Kruskal)

    题目描述 小$P$是个勤于思考的好孩子,自从学习了最大生成树后,他就一直在想:能否将边权范围从实数推广到复数呢?可是马上小$P$就发现了问题,复数之间的大小关系并没有定义.于是对于任意两个复数$z_1 ...