<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring 集成任務(wù)調(diào)度功能

          共 7234字,需瀏覽 15分鐘

           ·

          2019-12-15 23:26

          6d8a65134e5044c542666e572c90457d.webp

          5dc7ef641fe873dafadd744577060be6.webp

          來源:https://github.com/dunwu/spring-tutorial

          概述

          如果想在Spring中使用任務(wù)調(diào)度功能,除了集成調(diào)度框架Quartz這種方式,也可以使用Spring自己的調(diào)度任務(wù)框架。

          使用Spring的調(diào)度框架,優(yōu)點是:支持注解@Scheduler,可以省去大量的配置。

          實時觸發(fā)調(diào)度任務(wù)

          TaskScheduler接口

          Spring3引入了TaskScheduler接口,這個接口定義了調(diào)度任務(wù)的抽象方法。

          TaskScheduler接口的聲明:

          public?interface?TaskScheduler?{

          ????ScheduledFuture schedule(Runnable task, Trigger trigger);

          ????ScheduledFuture schedule(Runnable task, Date startTime);

          ????ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long?period);

          ????ScheduledFuture scheduleAtFixedRate(Runnable task, long?period);

          ????ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long?delay);

          ????ScheduledFuture scheduleWithFixedDelay(Runnable task, long?delay);

          }

          從以上方法可以看出TaskScheduler有兩類重要參數(shù):

          • 一個是要調(diào)度的方法,即一個實現(xiàn)了Runnable接口的線程類的run()方法;
          • 另一個就是觸發(fā)條件。
          TaskScheduler接口的實現(xiàn)類它有三個實現(xiàn)類:DefaultManagedTaskSchedulerThreadPoolTaskSchedulerTimerManagerTaskScheduler
          • DefaultManagedTaskScheduler:基于JNDI的調(diào)度器。
          • TimerManagerTaskScheduler:托管commonj.timers.TimerManager實例的調(diào)度器
          • ThreadPoolTaskScheduler:提供線程池管理的調(diào)度器,它也實現(xiàn)了TaskExecutor接口,從而使的單一的實例可以盡可能快地異步執(zhí)行。

          Trigger接口

          Trigger接口抽象了觸發(fā)條件的方法。Trigger接口的聲明:
          public?interface?Trigger?{
          ????Date nextExecutionTime(TriggerContext triggerContext);
          }
          Trigger接口的實現(xiàn)類CronTrigger:實現(xiàn)了cron規(guī)則的觸發(fā)器類(和Quartz的cron規(guī)則相同)。PeriodicTrigger:實現(xiàn)了一個周期性規(guī)則的觸發(fā)器類(例如:定義觸發(fā)起始時間、間隔時間等)。

          完整范例

          實現(xiàn)一個調(diào)度任務(wù)的功能有以下幾個關(guān)鍵點:(1) 定義調(diào)度器在spring-bean.xml中進行配置使用task:scheduler標簽定義一個大小為10的線程池調(diào)度器,spring會實例化一個ThreadPoolTaskScheduler
          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:mvc="http://www.springframework.org/schema/mvc"
          ???????xmlns:task="http://www.springframework.org/schema/task"
          ???????xsi:schemaLocation="http://www.springframework.org/schema/beans
          ???????http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          ???????http://www.springframework.org/schema/mvc
          ???????http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
          ???????http://www.springframework.org/schema/task
          ???????http://www.springframework.org/schema/task/spring-task-3.1.xsd"
          >

          ??<mvc:annotation-driven/>
          ??<task:scheduler?id="myScheduler"?pool-size="10"/>
          beans>
          注:不要忘記引入xsd:
          http://www.springframework.org/schema/task
          http://www.springframework.org/schema/task/spring-task-3.1.xsd
          (2) 定義調(diào)度任務(wù)定義實現(xiàn)Runnable接口的線程類。
          import?org.slf4j.Logger;
          import?org.slf4j.LoggerFactory;

          public?class?DemoTask?implements?Runnable?{
          ????final?Logger logger = LoggerFactory.getLogger(this.getClass());

          ????@Override
          ????public?void?run()?{
          ????????logger.info("call DemoTask.run");
          ????}
          }
          (3) 裝配調(diào)度器,并執(zhí)行調(diào)度任務(wù)在一個Controller類中用@Autowired注解裝配TaskScheduler然后調(diào)動TaskScheduler對象的schedule方法啟動調(diào)度器,就可以執(zhí)行調(diào)度任務(wù)了。
          @Controller
          @RequestMapping("/scheduler")
          public class SchedulerController {
          ????@Autowired
          ????TaskScheduler scheduler;

          ????@RequestMapping(value = "/start", method = RequestMethod.POST)
          ????public void start() {
          ????????scheduler.schedule(new DemoTask(), new CronTrigger("0/5 * * * * *"));
          ????}
          }
          訪問/scheduler/start接口,啟動調(diào)度器,可以看到如下日志內(nèi)容:
          13:53:15.010?myScheduler-1?o.zp.notes.spring.scheduler.DemoTask.run?-?call?DemoTask.run
          13:53:20.003?myScheduler-1?o.zp.notes.spring.scheduler.DemoTask.run?-?call?DemoTask.run
          13:53:25.004?myScheduler-2?o.zp.notes.spring.scheduler.DemoTask.run?-?call?DemoTask.run
          13:53:30.005?myScheduler-1?o.zp.notes.spring.scheduler.DemoTask.run?-?call?DemoTask.run

          @Scheduler的使用方法

          Spring的調(diào)度器一個很大的亮點在于@Scheduler注解,這可以省去很多繁瑣的配置。

          啟動注解

          使用@Scheduler注解先要使用啟動注解開關(guān)。例:
          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:mvc="http://www.springframework.org/schema/mvc"?
          ???????xmlns:task="http://www.springframework.org/schema/task"
          ???????xsi:schemaLocation="http://www.springframework.org/schema/beans
          ???????http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          ???????http://www.springframework.org/schema/mvc
          ???????http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
          ???????http://www.springframework.org/schema/task
          ???????http://www.springframework.org/schema/task/spring-task-3.1.xsd"
          >

          ??<mvc:annotation-driven/>
          ??<task:annotation-driven?executor="myExecutor"?scheduler="myScheduler"/>
          ??<task:executor?id="myExecutor"?pool-size="5"/>
          ??<task:scheduler?id="myScheduler"?pool-size="10"/>
          beans>

          @Scheduler定義觸發(fā)條件

          例:使用fixedDelay指定觸發(fā)條件為每5000毫秒執(zhí)行一次。注意:必須在上一次調(diào)度成功后的5000秒才能執(zhí)行。
          @Scheduled(fixedDelay=5000)
          public?void?doSomething()?{
          ????// something that should execute periodically
          }
          例:使用fixedRate指定觸發(fā)條件為每5000毫秒執(zhí)行一次。注意:無論上一次調(diào)度是否成功,5000秒后必然執(zhí)行。
          @Scheduled(fixedRate=5000)
          public?void?doSomething()?{
          ????// something that should execute periodically
          }
          例:使用initialDelay指定方法在初始化1000毫秒后才開始調(diào)度。
          @Scheduled(initialDelay=1000, fixedRate=5000)
          public?void?doSomething()?{
          ????// something that should execute periodically
          }
          例:使用cron表達式指定觸發(fā)條件為每5000毫秒執(zhí)行一次。cron規(guī)則和Quartz中的cron規(guī)則一致。
          @Scheduled(cron="*/5 * * * * MON-FRI")
          public?void?doSomething()?{
          ????// something that should execute on weekdays only
          }

          完整范例

          (1) 啟動注解開關(guān),并定義調(diào)度器和執(zhí)行器
          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:mvc="http://www.springframework.org/schema/mvc"?
          ???????xmlns:task="http://www.springframework.org/schema/task"
          ???????xsi:schemaLocation="http://www.springframework.org/schema/beans
          ???????http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          ???????http://www.springframework.org/schema/mvc
          ???????http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
          ???????http://www.springframework.org/schema/task
          ???????http://www.springframework.org/schema/task/spring-task-3.1.xsd"
          >


          ??<mvc:annotation-driven/>
          ??<task:annotation-driven?executor="myExecutor"?scheduler="myScheduler"/>
          ??<task:executor?id="myExecutor"?pool-size="5"/>
          ??<task:scheduler?id="myScheduler"?pool-size="10"/>
          beans>
          (2) 使用@Scheduler注解來修飾一個要調(diào)度的方法下面的例子展示了@Scheduler注解定義觸發(fā)條件的不同方式。
          /**
          ?* @description?使用@Scheduler注解調(diào)度任務(wù)范例
          ?* @author?Vicotr Zhang
          ?* @date?2016年8月31日
          ?*/

          @Component
          public?class?ScheduledMgr?{
          ????private?final?SimpleDateFormat dateFormat = new?SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

          ????final?Logger logger = LoggerFactory.getLogger(this.getClass());

          ????/**
          ?????* 構(gòu)造函數(shù)中打印初始化時間
          ?????*/

          ????public?ScheduledMgr()?{
          ????????logger.info("Current time: {}", dateFormat.format(new?Date()));
          ????}

          ????/**
          ?????* fixedDelay屬性定義調(diào)度間隔時間。調(diào)度需要等待上一次調(diào)度執(zhí)行完成。
          ?????*/

          ????@Scheduled(fixedDelay = 5000)
          ????public?void?testFixedDelay()?throws?Exception {
          ????????Thread.sleep(6000);
          ????????logger.info("Current time: {}", dateFormat.format(new?Date()));
          ????}

          ????/**
          ?????* fixedRate屬性定義調(diào)度間隔時間。調(diào)度不等待上一次調(diào)度執(zhí)行完成。
          ?????*/

          ????@Scheduled(fixedRate = 5000)
          ????public?void?testFixedRate()?throws?Exception {
          ????????Thread.sleep(6000);
          ????????logger.info("Current time: {}", dateFormat.format(new?Date()));
          ????}

          ????/**
          ?????* initialDelay屬性定義初始化后的啟動延遲時間
          ?????*/

          ????@Scheduled(initialDelay = 1000, fixedRate = 5000)
          ????public?void?testInitialDelay()?throws?Exception {
          ????????Thread.sleep(6000);
          ????????logger.info("Current time: {}", dateFormat.format(new?Date()));
          ????}

          ????/**
          ?????* cron屬性支持使用cron表達式定義觸發(fā)條件
          ?????*/

          ????@Scheduled(cron = "0/5 * * * * ?")
          ????public?void?testCron()?throws?Exception {
          ????????Thread.sleep(6000);
          ????????logger.info("Current time: {}", dateFormat.format(new?Date()));
          ????}
          }
          我刻意設(shè)置觸發(fā)方式的間隔都是5s,且方法中均有Thread.sleep(6000);語句。從而確保方法在下一次調(diào)度觸發(fā)時間點前無法完成執(zhí)行,來看一看各種方式的表現(xiàn)吧。啟動spring項目后,spring會掃描@Component注解,然后初始化ScheduledMgr。接著,spring會掃描@Scheduler注解,初始化調(diào)度器。調(diào)度器在觸發(fā)條件匹配的情況下開始工作,輸出日志。截取部分打印日志來進行分析。
          10:58:46.479?localhost-startStop-1?o.z.n.s.scheduler.ScheduledTasks.<init> -?Current?time: 2016-08-31?10:58:46
          10:58:52.523?myScheduler-1?o.z.n.s.scheduler.ScheduledTasks.testFixedRate?-?Current?time: 2016-08-31?10:58:52
          10:58:52.523?myScheduler-3?o.z.n.s.scheduler.ScheduledTasks.testFixedDelay?-?Current?time: 2016-08-31?10:58:52
          10:58:53.524?myScheduler-2?o.z.n.s.scheduler.ScheduledTasks.testInitialDelay?-?Current?time: 2016-08-31?10:58:53
          10:58:55.993?myScheduler-4?o.z.n.s.scheduler.ScheduledTasks.testCron?-?Current?time: 2016-08-31?10:58:55
          10:58:58.507?myScheduler-1?o.z.n.s.scheduler.ScheduledTasks.testFixedRate?-?Current?time: 2016-08-31?10:58:58
          10:58:59.525?myScheduler-5?o.z.n.s.scheduler.ScheduledTasks.testInitialDelay?-?Current?time: 2016-08-31?10:58:59
          10:59:03.536?myScheduler-3?o.z.n.s.scheduler.ScheduledTasks.testFixedDelay?-?Current?time: 2016-08-31?10:59:03
          10:59:04.527?myScheduler-1?o.z.n.s.scheduler.ScheduledTasks.testFixedRate?-?Current?time: 2016-08-31?10:59:04
          10:59:05.527?myScheduler-4?o.z.n.s.scheduler.ScheduledTasks.testInitialDelay?-?Current?time: 2016-08-31?10:59:05
          10:59:06.032?myScheduler-2?o.z.n.s.scheduler.ScheduledTasks.testCron?-?Current?time: 2016-08-31?10:59:06
          10:59:10.534?myScheduler-9?o.z.n.s.scheduler.ScheduledTasks.testFixedRate?-?Current?time: 2016-08-31?10:59:10
          10:59:11.527?myScheduler-10?o.z.n.s.scheduler.ScheduledTasks.testInitialDelay?-?Current?time: 2016-08-31?10:59:11
          10:59:14.524?myScheduler-4?o.z.n.s.scheduler.ScheduledTasks.testFixedDelay?-?Current?time: 2016-08-31?10:59:14
          10:59:15.987?myScheduler-6?o.z.n.s.scheduler.ScheduledTasks.testCron?-?Current?time: 2016-08-31?10:59:15
          構(gòu)造方法打印一次,時間點在10:58:46。testFixedRate打印四次,每次間隔6秒。說明,fixedRate不等待上一次調(diào)度執(zhí)行完成,在間隔時間達到時立即執(zhí)行。testFixedDelay打印三次,每次間隔大于6秒,且時間不固定。說明,fixedDelay等待上一次調(diào)度執(zhí)行成功后,開始計算間隔時間,再執(zhí)行。testInitialDelay第一次調(diào)度時間和構(gòu)造方法調(diào)度時間相隔7秒。說明,initialDelay在初始化后等待指定的延遲時間才開始調(diào)度。testCron打印三次,時間間隔并非5秒或6秒,顯然,cron等待上一次調(diào)度執(zhí)行成功后,開始計算間隔時間,再執(zhí)行。此外,可以從日志中看出,打印日志的線程最多只有10個,說明2.1中的調(diào)度器線程池配置生效。

          - End -

          bf6eaceba0c350390c1ad9b4470ceb23.webp

          術(shù)轉(zhuǎn)


          面試題系列教程??點擊-->?面試題技術(shù)干貨連載目錄?跳轉(zhuǎn)


          Maven系列教程??點擊-->?Maven技術(shù)干貨連載目錄?跳轉(zhuǎn)


          MyBatis系列教程??點擊-->?MyBatis技術(shù)干貨連載目錄?跳轉(zhuǎn)


          JVM調(diào)優(yōu)總結(jié)系列教程??點擊-->?JVM調(diào)優(yōu)技術(shù)干貨連載目錄?跳轉(zhuǎn)





          ,?110a23a333da7d4ff272e34b4e3a8bdb.webp

          瀏覽 32
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产三级在线观看 | 中文字幕无码久久 | 在线精品福利 | 在线观看国产福利视频 | 青草福利在线视频 |