第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. Linux用户的基本操作1 用户相关信息 及useradd /usermod 部分

    目录 linux 用户管理 - 用户的基本操作 用户管理 用户的相关命令 linux 用户管理 - 用户的基本操作 用户管理 1.什么是用户? 用户指的是能够正常登录Linux或windows系统 2 ...

  2. springboot+HttpInvoke 实现RPC调用

    开始用springboot2+hession4实现RPC服务时,发现第一个服务可以调用成功,但第二个就一直报 '<' is an unknown code.第一个服务还是可以调用的.参考网上的方 ...

  3. django搭建一个小型的服务器运维网站-查看服务器中的日志与前端的datatable的利用

    目录 项目介绍和源码: 拿来即用的bootstrap模板: 服务器SSH服务配置与python中paramiko的使用: 用户登陆与session; 最简单的实践之修改服务器时间: 查看和修改服务器配 ...

  4. 如何提高SMTP邮件的安全性?从而不被黑客窃听

    简单邮件传输协议(SMTP)用于在邮件服务器之间进行邮件传输,并且传统上是不安全的,因此容易被黑客窃听.命名实体的基于DNS的认证(国家统计局)用于SMTP提供了邮件传输更安全的方法,并逐渐变得越来越 ...

  5. 关于在IOS中 contenteditable=true 无法输入的问题

    解决: 1.添加样式-webkit-user-select:text 2.如果引入了fastclick,需要添加个类名 needsclick 来源于知乎(https://www.zhihu.com/q ...

  6. ESP8266-12F 中断

    外部中断: 基于ESP8266的NodeMcu的数字IO的中断功能是通过attachInterrupt,detachInterrupt函数所支持的.除了D0/GPIO16,中断可以绑定到任意GPIO的 ...

  7. bullet学习日记

    最近需要bullet用物理引擎做一个测量类的项目,因为半途接手,物理部分其实已经实现,但犹于对bullet基本不了解,导致相关部分完全改不动,这两天静下心来把物理引擎用法了解了一翻,顺便做点笔记,以便 ...

  8. Jquery TextBox进入focus的时候 改变background-color

    <!DOCTYPE html><html><head><script src="/jquery/jquery-1.11.1.min.js" ...

  9. 转载--C++的反思

    转载自http://blog.csdn.net/yapian8/article/details/46983319 最近两年 C++又有很多人出来追捧,并且追捧者充满了各种优越感,似乎不写 C++你就一 ...

  10. size_t是什么?

    在32位编译器下size_t可看做unsigned int: 在64位编译器下size_t可看做unsigned long long: sizeof返回的数据类型就为size_t. C++之size_ ...