Spring的任务调度@Scheduled注解——task:scheduler和task:executor的解析

applicationContext 的配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd"xmlns:task="http://www.springframework.org/schema/task"><context:annotation-config /><task:annotation-driven scheduler="myScheduler" executor="myExecutor"/><!-- 调度线程池配置 --><task:scheduler id="myScheduler" pool-size="5"/><!-- 执行线程池配置 --><task:executor id="myExecutor" pool-size="5"/><context:component-scan base-package="com.zaimeibian" /></beans>
package com.zaimeibian.task;import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;@Component
public class PrintTask {DateFormat df = new SimpleDateFormat("HH:mm:ss");// 这个Async注解,代表当前任务是要异步执行的@Async@Scheduled(fixedRate = 5000)public void printA(){System.out.println("A执行 " + df.format(new Date()));try {Thread.sleep(10000);} catch (InterruptedException e) {}System.out.println("A打印输出 " + df.format(new Date())+ Thread.currentThread());}@Scheduled(fixedRate = 5000)public void printB(){System.out.println("B执行 " + df.format(new Date()));try {Thread.sleep(10000);} catch (InterruptedException e) {}System.out.println("B打印输出 " + df.format(new Date())+ Thread.currentThread());}@Scheduled(fixedRate = 5000)public void printC(){System.out.println("C执行 " + df.format(new Date()));try {Thread.sleep(10000);} catch (InterruptedException e) {}System.out.println("C打印输出 " + df.format(new Date())+ Thread.currentThread());}// 配置initialDelay的任务是在容器启动后延迟一定时间才开始调度@Scheduled(fixedRate = 5000, initialDelay=1000)public void printD(){System.out.println("D执行 " + df.format(new Date()));try {Thread.sleep(30000);} catch (InterruptedException e) {}System.out.println("D打印输出 " + df.format(new Date())+ Thread.currentThread());}// 配置initialDelay的任务是在容器启动后延迟一定时间才开始调度@Scheduled(fixedRate = 5000, initialDelay=1000)public void printE(){System.out.println("E执行 " + df.format(new Date()));try {Thread.sleep(30000);} catch (InterruptedException e) {}System.out.println("E打印输出 " + df.format(new Date())+ Thread.currentThread());}}

这里,fixDelay 和 fixRate 参数代表每个任务,前者在上一个任务调度完成后,延迟一定的时间执行。而后者可以在每间隔一定时间就执行新任务(但这里与 executor 的参数有关)。下面的试验会详细说明这两个参数。
Spring 的任务调度线程池,即

<task:scheduler id="myScheduler" pool-size="5"/>

如果不配置,那么默认值是 1 ,即结果是所有声明的任务,都是串行执行的,比如代码中的 A/B/C/D/E 五个任务,在默认值是 1 的情况下,只能一个个串行来执行。不能出现并行的情况。
可以将参数改为 1 ,运行,输出如下:

B执行 12:16:36
B打印输出 12:16:46Thread[myScheduler-1,5,main]
A执行 12:16:46
A打印输出 12:16:56Thread[myScheduler-1,5,main]
C执行 12:16:56
C打印输出 12:17:06Thread[myScheduler-1,5,main]
D执行 12:17:06
D打印输出 12:17:36Thread[myScheduler-1,5,main]
E执行 12:17:36
E打印输出 12:18:06Thread[myScheduler-1,5,main]
B执行 12:18:06
B打印输出 12:18:16Thread[myScheduler-1,5,main]
A执行 12:18:16
A打印输出 12:18:26Thread[myScheduler-1,5,main]
C执行 12:18:26
C打印输出 12:18:36Thread[myScheduler-1,5,main]
D执行 12:18:36
D打印输出 12:19:06Thread[myScheduler-1,5,main]
E执行 12:19:06
E打印输出 12:19:36Thread[myScheduler-1,5,main]
B执行 12:19:36
B打印输出 12:19:46Thread[myScheduler-1,5,main]
A执行 12:19:46
A打印输出 12:19:56Thread[myScheduler-1,5,main]

可以看到只有 myScheduler-1 这一个调度线程来调度这五个任务,任务之间只能串行,即等待上个任务完成后释放调度线程,然后调度线程才能调度执行下一个任务。

然后我们还改回调度线程池 5 个线程池大小,运行:

C执行 12:23:04
A执行 12:23:04
B执行 12:23:04
E执行 12:23:05
D执行 12:23:05
C打印输出 12:23:14Thread[myScheduler-2,5,main]
C执行 12:23:14
A打印输出 12:23:14Thread[myScheduler-3,5,main]
A执行 12:23:14
B打印输出 12:23:14Thread[myScheduler-1,5,main]
B执行 12:23:14
C打印输出 12:23:24Thread[myScheduler-2,5,main]
C执行 12:23:24
A打印输出 12:23:24Thread[myScheduler-3,5,main]
A执行 12:23:24
B打印输出 12:23:24Thread[myScheduler-1,5,main]
B执行 12:23:24
C打印输出 12:23:34Thread[myScheduler-2,5,main]
A打印输出 12:23:34Thread[myScheduler-3,5,main]
C执行 12:23:34
A执行 12:23:34
B打印输出 12:23:34Thread[myScheduler-1,5,main]
B执行 12:23:34
E打印输出 12:23:35Thread[myScheduler-4,5,main]
E执行 12:23:35
D打印输出 12:23:35Thread[myScheduler-5,5,main]
D执行 12:23:35

可以看到,如果每个任务都有一个调度线程来处理,那么就是很理想的情况,各个任务之间是并行的,互不干扰各自独立,按照各自的时间来触发。(可以看到 1-5 这 5 个线程都在各自调度自己的任务)
这里还要注意一点,fixDelay 和 fixRate 看上去似乎是一样的,在每个任务的调度线程中,都是必须上一个执行完毕后,等待配置的时间后,再开始下一次的执行。是不是 fixRate 参数不起作用呢?因为不是说 fixRate 是间隔一定时间执行,而不需要等待上一个任务执行完毕么?

这里引入另一个参数,可以看任务 A 上方注释掉的 @Async 注解:这个注解,代表可以异步执行。异步执行的话,调度线程池就会不用当前调度线程来执行,而是交给 task:executor 这个执行线程池来执行。
我们来运行,这里为了更好的说明,我们可以把 A 的 fixRate 改为 2秒 ,看运行结果:

B执行 12:34:44
C执行 12:34:44
A执行 12:34:44
D执行 12:34:45
E执行 12:34:45
A执行 12:34:46
A执行 12:34:48
A执行 12:34:50
A执行 12:34:52
B打印输出 12:34:54Thread[myScheduler-2,5,main]
B执行 12:34:54
C打印输出 12:34:54Thread[myScheduler-3,5,main]
A打印输出 12:34:54Thread[myExecutor-1,5,main]
C执行 12:34:54
A执行 12:34:54
A打印输出 12:34:56Thread[myExecutor-2,5,main]
A执行 12:34:56
A打印输出 12:34:58Thread[myExecutor-3,5,main]
A执行 12:34:58
A打印输出 12:35:00Thread[myExecutor-4,5,main]
A执行 12:35:00
A打印输出 12:35:02Thread[myExecutor-5,5,main]
A执行 12:35:02
B打印输出 12:35:04Thread[myScheduler-2,5,main]
B执行 12:35:04
C打印输出 12:35:04Thread[myScheduler-3,5,main]
A打印输出 12:35:04Thread[myExecutor-1,5,main]
C执行 12:35:04
A执行 12:35:04
A打印输出 12:35:06Thread[myExecutor-2,5,main]

里 A 任务的线程是 myExecutor-1 到 myExecutor-5,说明 myScheduler-1 这个调度线程调度了 A 任务,但是交给了线程池中的 myExecutor 中的执行线程来具体执行的。
所以,配置 task:scheduler 参数的线程池,是为了根据任务总数来分配调度线程池的大小;而配置 task:executor ,是为了某个任务如果要异步的执行时,实现当前任务内的多线程并发。

Spring的任务调度@Scheduled注解——task:scheduler和task:executor的解析相关推荐

  1. 关于Spring 任务调度之task:scheduler与task:executor配置的详解

    关于Spring 任务调度之task:scheduler与task:executor配置的详解 其实就是Spring定时器中配置文件中一些配置信息,由于笔者自己是头一次使用,有些配置详细不太明白,随即 ...

  2. Spring:任务调度之task:scheduler与task:executor配置的详解

    其实就是Spring定时器中配置文件中一些配置信息,由于笔者自己是头一次使用,有些配置详细不太明白,随即研究了一番,于是想记录一下,有需要的小伙伴可以参考,也方便日后自己查阅. 首先,创建一个仅仅包含 ...

  3. spring定时任务(@Scheduled注解)

    (一)在xml里加入task的命名空间 xmlns:task="http://www.springframework.org/schema/task" http://www.spr ...

  4. spring自定义定时任务- @Scheduled注解

    之前设置定时任务都是设置的固定数量的, 如果想动态的添加定时任务无法实现, 所以现在自己手动依赖Spring ,完成了一个定时任务的管理功能. 新建一个定时任务的配置类, 从数据库中读取配置的定时任务 ...

  5. Spring的@Scheduled注解实现定时任务

    Spring的@Scheduled注解实现定时任务 [简介篇] 项目经常会用到定时任务,实现定时任务的方式有很多种.在Spring框架中,实现定时任务很简单,常用的实现方式是使用注解@Schedule ...

  6. scheduled每天下午1点执行一次_在Spring Boot项目中使用@Scheduled注解实现定时任务...

    在java开发中定时任务的实现有多种方式,jdk有自己的定时任务实现方式,很多框架也有定时任务的实现方式.这里,我介绍一种很简单的实现方式,在Spring Boot项目中使用两个注解即可实现. 在sp ...

  7. SpringBoot定时任务@Scheduled注解详解

    SpringBoot定时任务@Scheduled注解详解 项目开发中,经常会遇到定时任务的场景,Spring提供了@Scheduled注解,方便进行定时任务的开发 概述 要使用@Scheduled注解 ...

  8. Spring Boot 任务调度

    应用场景 有贷款的同学每个月都会收到催还贷款的提醒短信,每天上班.上课前钉钉的打卡提醒,等等.类似这种定时重复的功能,我们就可以使用任务调度来实现. 任务调度框架 调度框架 说明 Timer JDK自 ...

  9. java scheduled_Spring内置定时任务调度@Scheduled使用详解

    Spring提供了@Scheduled注解用于定时任务. 一.@Scheduled的基本使用 启用调度支持:@EnableScheduling 可以将@Scheduled注释与触发器元数据一起添加到方 ...

最新文章

  1. 微信跳一跳高分辅助踩坑
  2. 在Kubernetes上运行SAP UI5应用(下): 一个例子体会Kubernetes内容器的高可用性和弹性伸缩...
  3. 11月21日spring mvc的表单校验培训日记
  4. commit与rollback命令
  5. python和java哪个-Python和Java到底哪个更好?
  6. Nowcoder 提高组练习赛-R3
  7. Android中使用ContentProvider进行跨进程方法调用
  8. 前端学习(2469):echart复习电商管理通过erchart加载数据
  9. 信息系统项目管理系列之九:项目质量管理
  10. 研究做得好,贡献也要大!腾讯AI Lab正式开源业内最大规模多标签图像数据集...
  11. android 开发问题集(一):SDK更新后 运行程序报错Location of the Android SDK has not been setup in the preferences
  12. spring-boot-2.0.3应用篇 - shiro集成
  13. RN react-navigation使用
  14. JavaScript:利用StringBuffer类提升+=拼接字符串效率
  15. The Willpower Instinct(自控力,意志力)
  16. 算法设计与分析基础(第3版)读书笔记(及几处翻译上的错误~~)
  17. Inside Real-Time Linux
  18. 通达OAV12报表中心
  19. 通过跳绳瘦下来是一种怎么样的体验?
  20. 综合布线容易忽略的问题

热门文章

  1. oracle基本的操作命令,oracle命令基本操作
  2. 蓝牙连接不上车要hfp_如何正确使用车载蓝牙播放器呢?
  3. [转载] StringBuffer和StringBuilder类
  4. stl min函数_std :: min()函数以及C ++ STL中的示例
  5. 获取列表中包含的元素数 在C#中
  6. java8 json转xml_2019-08-17java对象与json,xml互转
  7. 北航计算机学院博士机试考试题,北航2015考博真题回忆及全套资料 - 考博 - 小木虫 - 学术 科研 互动社区...
  8. freemarker的测试结果框架_java必背综合知识点总结(框架篇)
  9. ruby hash方法_Ruby中带有示例的Hash.keys方法
  10. golang的new函数_new()和make()函数以及Golang中的示例