第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。

最新文章

  1. 无中间变量交换swap(a,b)
  2. DAO实现查询
  3. (转)linux文件读写的流程
  4. 工作流模式与K2实现- (1)
  5. zoj3623 Battle Ships ——完全背包?简单DP!|| 泛化背包
  6. ES5 vs ES6
  7. 条形码Code128源代码
  8. 如何定制Sink扩展.Net Remoting功能
  9. Oracle EBS-SQL (INV-5):检查期间拉式物料领用记录数.sql
  10. iterm2 快捷键大全 Mac item2常用快捷键
  11. select省市联动选择城市 asp.net mvc4
  12. [Bootstrap 源码]——bootstrap源码之初始化
  13. poj-1207 THE 3n+1 problem
  14. 《k8s-1.13版本源码分析》- 调度器设计
  15. C#中的反射 Reflection
  16. SSM框架中各层的含义和联系
  17. python3+redis问题求解
  18. .Net中使用ODP.net访问Oracle数据库
  19. IPutils
  20. 2.2 dubbo-spi源码解析

热门文章

  1. Divergent series
  2. TCP/IP基础总结性学习(5)
  3. Spring Cloud第十二篇 | 消息总线Bus
  4. 关于web前端性能优化问题
  5. linux软件操作
  6. 一个错误导致懂了mac系统的PATH环境变量
  7. JDK5的新特性
  8. java 8 接口默认方法
  9. luogu 5471 [NOI2019]弹跳 KDtree + Dijkstra
  10. HDU 2825 Wireless Password ( Trie图 &amp;&amp; 状态压缩DP )