第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. MongoDB入门_相关网站

    几个重要的网站 1.MongoDB官网:https://www.mongodb.org 2.MongoDB的国内官网https://www.mongoing.com 3.MongoDB的中文文档htt ...

  2. 深度强化学习(Deep Reinforcement Learning)入门:RL base & DQN-DDPG-A3C introduction

    转自https://zhuanlan.zhihu.com/p/25239682 过去的一段时间在深度强化学习领域投入了不少精力,工作中也在应用DRL解决业务问题.子曰:温故而知新,在进一步深入研究和应 ...

  3. 常见 linux 命令

    1.find find . //列出当前目录及子目录下的所有文件和文件夹 find /home -name "*.txt" //在/home目录下查找以.txt结尾的文件名或路径 ...

  4. MYSQL数据导出与导入,secure_file_priv参数设置

    https://www.imooc.com/article/41883 MySQL 报错 [Code: 1290, SQL State: HY000]  The MySQL server is run ...

  5. Flask【第3篇】:蓝图、基于DBUtils实现数据库连接池、上下文管理等

    基于DBUtils实现数据库连接池 小知识: 1.子类继承父类的三种方式 class Dog(Animal): #子类 派生类 def __init__(self,name,breed, life_v ...

  6. Jackson常用工具类

    原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11983194.html Demo package org.fool.util; import com. ...

  7. Quick BI的宝藏工具——交叉表

    对于普通的表格展示数据,相信大家都非常熟悉了,今天给大家介绍的是BI领域的分析利器-交叉表,这个在BI分析场景中使用占比最多的分析利器.通过交叉表对数据的承载和管理,用户可以一目了然地分析出各种场景指 ...

  8. web上传大文件(>4G)有什么解决方案?

    众所皆知,web上传大文件,一直是一个痛.上传文件大小限制,页面响应时间超时.这些都是web开发所必须直面的. 本文给出的解决方案是:前端实现数据流分片长传,后面接收完毕后合并文件的思路. 实现文件夹 ...

  9. poj 3613Cow Relays

    Description For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a rel ...

  10. 约数定理(two)

    筛约数个数和 理论基础: 1.对n质因数分解,n=p1^k1 * p2^k2 * p3^k3 …… 则n的约数个数为(k1+1)*(k2+1)*(k3+1)…… 2.线性筛素数时,用i和素数pj来筛掉 ...