亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Quartz 2 定時(shí)任務(wù)(二):多線程并發(fā)執(zhí)行與數(shù)據(jù)共享

OpenDigg / 2705人閱讀

摘要:注意當(dāng)使用注解時(shí),為了避免并發(fā)時(shí),存儲數(shù)據(jù)造成混亂,強(qiáng)烈建議把注解也加上。示例假設(shè)定時(shí)任務(wù)的時(shí)間間隔為秒,但執(zhí)行時(shí)間是秒。當(dāng)設(shè)置以后程序會等任務(wù)執(zhí)行完畢后再去執(zhí)行,否則會在秒時(shí)再啟動新的線程執(zhí)行。

版權(quán)聲明:本文由吳仙杰創(chuàng)作整理,轉(zhuǎn)載請注明出處:https://segmentfault.com/a/1190000009128328

1. 禁止同一個(gè) JobDetail 中的多個(gè)實(shí)例并發(fā)執(zhí)行

Quartz 定時(shí)任務(wù)默認(rèn)都是并發(fā)執(zhí)行的,不會等待上一次任務(wù)執(zhí)行完畢,只要間隔時(shí)間到就會執(zhí)行,如果定時(shí)任執(zhí)行太長,會長時(shí)間占用資源,導(dǎo)致其它任務(wù)堵塞。

禁止并發(fā)執(zhí)行的意思并不是不能同時(shí)執(zhí)行多個(gè) Job,而是不能并發(fā)執(zhí)行同一個(gè) Job Definition(由 JobDetail 定義),但是可以同時(shí)執(zhí)行多個(gè)不同的 JobDetail,舉例說明,我們有一個(gè) Job 類,叫做 SayHelloJob,并在這個(gè) Job 上加了 @DisallowConcurrentExecution 注解,然后在這個(gè) Job上 定義了很多個(gè) JobDetail,如 sayHelloToJoeJobDetail,sayHelloToMikeJobDetail,那么當(dāng) scheduler 啟動時(shí),不會并發(fā)執(zhí)行多個(gè) sayHelloToJoeJobDetail 或者 sayHelloToMikeJobDetail,但可以同時(shí)執(zhí)行 sayHelloToJoeJobDetail 跟 sayHelloToMikeJobDetail。

1.1 使用 Spring 整合 Quartz 時(shí)

Spring 配置文件中加入:


1.2 Quartz 原生使用時(shí)

當(dāng)不使用 Spring 的時(shí)候就需要在 Job 的實(shí)現(xiàn)類上加 @DisallowConcurrentExecution 的注解。

2. 同一個(gè) JobDetail 中多個(gè)實(shí)例的數(shù)據(jù)共享

@PersistJobDataAfterExecution 是用在 Job 實(shí)現(xiàn)類上,表示一個(gè)有狀態(tài)的任務(wù),意思是當(dāng)正常執(zhí)行完 Job 后,JobDataMap 中的數(shù)據(jù)應(yīng)該被改動,以被下一次調(diào)用時(shí)用。

注意:當(dāng)使用 @PersistJobDataAfterExecution 注解時(shí),為了避免并發(fā)時(shí),存儲數(shù)據(jù)造成混亂,強(qiáng)烈建議@DisallowConcurrentExecution 注解也加上。

3. 示例

假設(shè)定時(shí)任務(wù)的時(shí)間間隔為 3 秒,但 job 執(zhí)行時(shí)間是 10 秒。當(dāng)設(shè)置 @DisallowConcurrentExecution 以后程序會等任務(wù)執(zhí)行完畢后再去執(zhí)行,否則會在 3 秒時(shí)再啟動新的線程執(zhí)行。

當(dāng)設(shè)置 @PersistJobDataAfterExecution 時(shí),在執(zhí)行完 Job 的 execution 方法后保存 JobDataMap 當(dāng)中固定數(shù)據(jù),以便任務(wù)在重復(fù)執(zhí)行的時(shí)候具有相同的 JobDataMap;在默認(rèn)情況下也就是沒有設(shè)置 @PersistJobDataAfterExecution 的時(shí)候每個(gè) job 都擁有獨(dú)立 JobDataMap。

任務(wù)類:

package org.quartz.examples;

import org.quartz.*;

import java.util.Date;

@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class TaskJob implements Job {

    public static final String NUM_EXECUTIONS = "NumExecutions";
    public static final String EXECUTION_DELAY = "ExecutionDelay";

    /**
     * 靜態(tài)變量可以保持工作狀態(tài),但無法達(dá)到預(yù)期效果
     */
    private static int _staticCounter = 0;

    /**
     * Quartz 每次執(zhí)行作業(yè)時(shí)都會重新實(shí)例化,非靜態(tài)變量無法保持工作狀態(tài)
     */
    private int _counter = 0;

    /**
     * 需要一個(gè)公共的空構(gòu)造方法,以便 scheduler 隨時(shí)實(shí)例化 job
     */
    public TaskJob() {
    }

    /**
     * 該方法實(shí)現(xiàn)需要執(zhí)行的任務(wù)
     */
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.err.println("---> " + context.getJobDetail().getKey() + " 運(yùn)行中[" + new Date() + "]");

        JobDataMap map = context.getJobDetail().getJobDataMap();

        int executeCount = 0;
        if (map.containsKey(NUM_EXECUTIONS)) {
            executeCount = map.getInt(NUM_EXECUTIONS);
        }

        // 增量計(jì)數(shù)并將其存儲回 JobDataMap,這樣可以適當(dāng)保持工作狀態(tài)
        executeCount++;
        map.put(NUM_EXECUTIONS, executeCount);

        // 只要有任務(wù)執(zhí)行都會遞增,無法達(dá)到預(yù)期效果
        _staticCounter++;

        // 本地變量遞增加,但實(shí)際上無法保持工作狀態(tài)
        _counter++;

        long delay = 5000L;
        if (map.containsKey(EXECUTION_DELAY)) {
            delay = map.getLong(EXECUTION_DELAY);
        }

        try {
            // 模擬一個(gè)耗時(shí)的 job
            Thread.sleep(delay);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.err.println(context.getJobDetail().getKey() + " 的靜態(tài)變量 _staticCounter 為:" + _staticCounter + ",非靜態(tài)變量 scheduler 為:" + _counter);
        System.err.println(context.getJobDetail().getKey() + " 完成了(" + executeCount + ")次 <---");
    }
}

任務(wù)調(diào)度類:

package org.quartz.examples;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.util.Date;

public class Executer {

    public void run() throws Exception {
        // 通過 schedulerFactory 獲取一個(gè)調(diào)度器
        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler sched = sf.getScheduler();

        // 創(chuàng)建 jobDetail 實(shí)例,綁定 Job 實(shí)現(xiàn)類
        // 指明 job 的名稱,所在組的名稱,以及綁定 job 類
        JobDetail job1 = JobBuilder.newJob(TaskJob.class)
                .withIdentity("statefulJob1", "group1")
                // 給定的鍵-值對添加到 JobDetail 的 JobDataMap 中
                .usingJobData(TaskJob.EXECUTION_DELAY, 10000L).build();

        // 定義調(diào)度觸發(fā)規(guī)則,先立即執(zhí)行一次,然后每隔 3 秒執(zhí)行一次
        SimpleTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(3)
                        .repeatForever())
                .build();

        // 把作業(yè)和觸發(fā)器注冊到任務(wù)調(diào)度中
        Date firstRunTime = sched.scheduleJob(job1, trigger);
        System.out.println(job1.getKey() + " 開始運(yùn)行于:" + firstRunTime + ",重復(fù):" + trigger.getRepeatCount() + " 次,每次間隔 "
                + trigger.getRepeatInterval() / 1000 + " 秒");

        // 任務(wù) job1 方法中拿到的 JobDataMap 的數(shù)據(jù)是共享的
        // 這里要注意一個(gè)情況: 就是 JobDataMap 的數(shù)據(jù)共享只針對一個(gè) job1 任務(wù)
        // 如果在下面在新增加一個(gè)任務(wù) 那么他們之間是不共享的,比如下面的 job2
        // 創(chuàng)建第二個(gè) JobDetail 實(shí)例
        JobDetail job2 = JobBuilder.newJob(TaskJob.class)
                .withIdentity("statefulJob2", "group1")
                // 給定的鍵-值對添加到 JobDetail 的 JobDataMap 中
                .usingJobData(TaskJob.EXECUTION_DELAY, 10000L)
                .build();

        // 定義調(diào)度觸發(fā)規(guī)則,先立即執(zhí)行一次,然后每隔 3 秒執(zhí)行一次
        trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger2", "group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().
                        withIntervalInSeconds(3)
                        .repeatForever()
                        // 指定失效時(shí)的策略
                        .withMisfireHandlingInstructionNowWithExistingCount())
                .build();

        // 這個(gè) job2 與 job1 執(zhí)行的 JobDataMap 不共享
        // 把作業(yè)和觸發(fā)器注冊到任務(wù)調(diào)度中
        firstRunTime = sched.scheduleJob(job2, trigger);
        System.out.println(job2.getKey() + " 開始運(yùn)行于:" + firstRunTime + ",重復(fù):" + trigger.getRepeatCount() + " 次,每次間隔 "
                + trigger.getRepeatInterval() / 1000 + " 秒");

        // 啟動計(jì)劃程序(實(shí)際上直到調(diào)度器已經(jīng)啟動才會開始運(yùn)行)
        sched.start();

        // 等待 60 秒,使我們的 job 有機(jī)會執(zhí)行
        Thread.sleep(60000);

        // 等待作業(yè)執(zhí)行完成時(shí)才關(guān)閉調(diào)度器
        sched.shutdown(true);

        SchedulerMetaData metaData = sched.getMetaData();
        System.out.println("一共運(yùn)行了:" + metaData.getNumberOfJobsExecuted() + " 個(gè)任務(wù)");
    }

    public static void main(String[] args) throws Exception {
        Executer example = new Executer();
        example.run();
    }
}

運(yùn)行結(jié)果:

group1.statefulJob1 開始運(yùn)行于:Wed Apr 19 17:04:22 CST 2017,重復(fù):-1 次,每次間隔 3 秒
group1.statefulJob2 開始運(yùn)行于:Wed Apr 19 17:04:22 CST 2017,重復(fù):-1 次,每次間隔 3 秒

---> group1.statefulJob2 運(yùn)行中[Wed Apr 19 17:04:22 CST 2017]
---> group1.statefulJob1 運(yùn)行中[Wed Apr 19 17:04:22 CST 2017]
group1.statefulJob2 的靜態(tài)變量 _staticCounter 為:2,非靜態(tài)變量 scheduler 為:1
group1.statefulJob1 的靜態(tài)變量 _staticCounter 為:2,非靜態(tài)變量 scheduler 為:1
group1.statefulJob2 完成了(1)次 <---
group1.statefulJob1 完成了(1)次 <---
---> group1.statefulJob1 運(yùn)行中[Wed Apr 19 17:04:32 CST 2017]
---> group1.statefulJob2 運(yùn)行中[Wed Apr 19 17:04:32 CST 2017]
group1.statefulJob1 的靜態(tài)變量 _staticCounter 為:4,非靜態(tài)變量 scheduler 為:1
group1.statefulJob1 完成了(2)次 <---
group1.statefulJob2 的靜態(tài)變量 _staticCounter 為:4,非靜態(tài)變量 scheduler 為:1
group1.statefulJob2 完成了(2)次 <---
---> group1.statefulJob1 運(yùn)行中[Wed Apr 19 17:04:42 CST 2017]
---> group1.statefulJob2 運(yùn)行中[Wed Apr 19 17:04:42 CST 2017]
group1.statefulJob2 的靜態(tài)變量 _staticCounter 為:6,非靜態(tài)變量 scheduler 為:1
group1.statefulJob1 的靜態(tài)變量 _staticCounter 為:6,非靜態(tài)變量 scheduler 為:1
group1.statefulJob1 完成了(3)次 <---
group1.statefulJob2 完成了(3)次 <---
---> group1.statefulJob1 運(yùn)行中[Wed Apr 19 17:04:52 CST 2017]
---> group1.statefulJob2 運(yùn)行中[Wed Apr 19 17:04:52 CST 2017]
group1.statefulJob2 的靜態(tài)變量 _staticCounter 為:8,非靜態(tài)變量 scheduler 為:1
group1.statefulJob2 完成了(4)次 <---
group1.statefulJob1 的靜態(tài)變量 _staticCounter 為:8,非靜態(tài)變量 scheduler 為:1
group1.statefulJob1 完成了(4)次 <---
---> group1.statefulJob2 運(yùn)行中[Wed Apr 19 17:05:02 CST 2017]
---> group1.statefulJob1 運(yùn)行中[Wed Apr 19 17:05:02 CST 2017]
group1.statefulJob2 的靜態(tài)變量 _staticCounter 為:10,非靜態(tài)變量 scheduler 為:1
group1.statefulJob1 的靜態(tài)變量 _staticCounter 為:10,非靜態(tài)變量 scheduler 為:1
group1.statefulJob2 完成了(5)次 <---
group1.statefulJob1 完成了(5)次 <---
---> group1.statefulJob1 運(yùn)行中[Wed Apr 19 17:05:12 CST 2017]
---> group1.statefulJob2 運(yùn)行中[Wed Apr 19 17:05:12 CST 2017]

group1.statefulJob2 的靜態(tài)變量 _staticCounter 為:12,非靜態(tài)變量 scheduler 為:1
group1.statefulJob2 完成了(6)次 <---
group1.statefulJob1 的靜態(tài)變量 _staticCounter 為:12,非靜態(tài)變量 scheduler 為:1
group1.statefulJob1 完成了(6)次 <---

一共運(yùn)行了:12 個(gè)任務(wù)
4. 參考

Quartz 線程處理

Quartz API

PS:本文針對的 Quartz 版本為 Quartz 2.2.3。官方下載地址:Quartz 2.2.3 .tar.gz

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/67057.html

相關(guān)文章

  • Quartz 2 定時(shí)任務(wù)(三):異常中斷處理

    摘要:注意為了共享在同一個(gè)中的,我們需要在上面這個(gè)實(shí)現(xiàn)類上加入和注解,詳見定時(shí)任務(wù)二多線程并發(fā)執(zhí)行與數(shù)據(jù)共享。捕獲異常,取消所有觸發(fā)器在我們捕獲異常時(shí),可以調(diào)用取消所有與這個(gè)作業(yè)有關(guān)的觸發(fā)器。 版權(quán)聲明:本文由吳仙杰創(chuàng)作整理,轉(zhuǎn)載請注明出處:https://segmentfault.com/a/1190000009141079 1. 作業(yè)異常 org.quartz.JobExecut...

    Hydrogen 評論0 收藏0
  • Quartz 2 定時(shí)任務(wù)(一):基本使用指南

    摘要:調(diào)度器就相當(dāng)于一個(gè)容器,裝載著任務(wù)和觸發(fā)器。用于指定額外的值。然而,如果指定并且第一號是星期六,那么觸發(fā)器的觸發(fā)在第三號周一,因?yàn)樗粫^一個(gè)月的日子的邊界。注意如果只是指定,則觸發(fā)器在月份中不會觸發(fā)。 版權(quán)聲明:本文由吳仙杰創(chuàng)作整理,轉(zhuǎn)載請注明出處:https://segmentfault.com/a/1190000009128277 1. Quartz 體系結(jié)構(gòu) Quartz 設(shè)計(jì)...

    Freelander 評論0 收藏0
  • SpringBoot中并發(fā)定時(shí)任務(wù)的實(shí)現(xiàn)、動態(tài)定時(shí)任務(wù)的實(shí)現(xiàn)(看這一篇就夠了)

    摘要:也是自帶的一個(gè)基于線程池設(shè)計(jì)的定時(shí)任務(wù)類。其每個(gè)調(diào)度任務(wù)都會分配到線程池中的一個(gè)線程執(zhí)行,所以其任務(wù)是并發(fā)執(zhí)行的,互不影響。 原創(chuàng)不易,如需轉(zhuǎn)載,請注明出處https://www.cnblogs.com/baixianlong/p/10659045.html,否則將追究法律責(zé)任?。?! 一、在JAVA開發(fā)領(lǐng)域,目前可以通過以下幾種方式進(jìn)行定時(shí)任務(wù) 1、單機(jī)部署模式 Timer:jdk中...

    BWrong 評論0 收藏0
  • Quartz實(shí)現(xiàn)工作流

    摘要:也有,觸發(fā)點(diǎn)和相關(guān),和我們的需求關(guān)系不大,暫忽略。實(shí)現(xiàn)為每個(gè)算法任務(wù)創(chuàng)建一個(gè),任務(wù)失敗不能啟動后續(xù)任務(wù),所以在運(yùn)行失敗的情況下,需要把啟動的刪除掉。需要自己在中實(shí)現(xiàn)多個(gè)依賴是否完成的檢查。后續(xù)主線程的任務(wù)就是檢查工作流是否已經(jīng)完成。 Quartz簡介 作為一個(gè)優(yōu)秀的開源調(diào)度框架,Quartz 具有以下特點(diǎn):強(qiáng)大的調(diào)度功能,支持立即調(diào)度、定時(shí)調(diào)度、周期調(diào)度、并發(fā)調(diào)度; 靈活的應(yīng)用方式,支...

    Apollo 評論0 收藏0
  • 微服務(wù)架構(gòu)中,次淺封裝實(shí)踐

    摘要:三實(shí)踐案例案例簡介分布式系統(tǒng)中,微服務(wù)基礎(chǔ)組件等,系統(tǒng)中間件,等,對常用功能配置等,進(jìn)行二次淺封裝并統(tǒng)一集成管理,以滿足日常開發(fā)中基礎(chǔ)環(huán)境搭建與臨時(shí)工具的快速實(shí)現(xiàn)。 一、背景簡介 分布式系統(tǒng)中存在很多拆分的服務(wù),在不斷迭代升級的過程中,會出現(xiàn)如下常見的棘手情況: 某個(gè)技術(shù)組件版本升級,依賴包升級導(dǎo)致部分語法或者API過期,或者組件修復(fù)緊急的問題,從而會導(dǎo)致分布式系統(tǒng)下各個(gè)服...

    Hujiawei 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<