1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        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)類:DefaultManagedTaskScheduler、ThreadPoolTaskScheduler、TimerManagerTaskScheduler
        • 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
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

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

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            欧洲成人无码 | 爆操91 | 国内毛片毛片毛片毛片毛片毛片毛片毛片毛片毛片毛片毛片 | 中国女人野外做爰a正片 | 亚洲精品精华液一区 | 操逼网站观看 | 三级黄色电视 | 国产精品福利午夜在线观看 | 嗯~用力啊~嗯 | 91制片厂毛片操逼视频 |