成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

那些年,我們用過的“定時調(diào)度”

PrototypeZ / 1870人閱讀

摘要:也是自帶的一個基于線程池設(shè)計的定時任務(wù)類。問題的解決方式,可以通過自定義來修改當(dāng)前的線程池。問題,則可以直接使用類實(shí)現(xiàn)自定義的定時調(diào)度規(guī)則。

定時調(diào)度

作為后端開發(fā)人員,我們總會遇到這樣的業(yè)務(wù)場景:每周同步一批數(shù)據(jù);每半個小時檢查一遍服務(wù)器運(yùn)行狀況;每天早上八點(diǎn)給用戶發(fā)送一份包含今日待辦事項的郵件,等等。

這些場景中都離不開“定時器”,就像一個定好時間規(guī)則的鬧鐘,它會在指定時間觸發(fā),執(zhí)行我們想要定義的調(diào)度任務(wù)。那么我們今天就來數(shù)一下,那些年我們用過的“定時調(diào)度”。

1. job (oracle)

從剛工作就一直使用oracle數(shù)據(jù)庫,最早接觸的定時任務(wù)就是oracle數(shù)據(jù)庫的job。job有定時執(zhí)行的功能,可以在指定的時間點(diǎn)或每天的某個時間點(diǎn)自行執(zhí)行任務(wù)。 而且oracle重新啟動后,job會繼續(xù)運(yùn)行,不用重新啟動。

而且job的機(jī)制非常完備,可以查詢相關(guān)的表或視圖,查詢job的定時規(guī)則和執(zhí)行情況。缺點(diǎn)是作為oracle數(shù)據(jù)庫層面的工具,自定義功能擴(kuò)展,二次開發(fā)的難度比較大。

1.1 創(chuàng)建job

DECLARE
  job NUMBER;
BEGIN
    sys.dbms_job.submit(job => job,

    what => "prc_name;",                          --執(zhí)行的存儲過程的名字

    next_date => to_date("22-11-2013 09:09:41", "dd-mm-yyyy hh24:mi:ss"), --下一次執(zhí)行時間

    interval =>"sysdate+1/24");            --每天24小時,即每小時運(yùn)行prc_name過程一次
END;

-- job參數(shù)是輸出參數(shù),由submit()過程返回的binary_ineger,這個值用來唯一標(biāo)識一個工作。一般定義一個變量接收,可以去user_jobs視圖查詢job值。
-- what參數(shù)是將被執(zhí)行的PL/SQL代碼塊,存儲過程名稱等。
-- next_date參數(shù)指識何時將運(yùn)行這個工作。
-- interval參數(shù)何時這個工作將被重執(zhí)行

1.2 刪除job

DECLARE
BEGIN
  dbms_job.remove(1093);  -- 1093為當(dāng)前需要刪除的 job 值
  COMMIT;
END;

1.3 查詢job

-- 查詢當(dāng)前用戶的job
select * from user_jobs;
-- 查詢所有job
select * from dba_jobs;
-- 查詢所有運(yùn)行中的job
select * from dba_jobs_running;
2. crontab (linux)

crond 是linux下用來周期性的執(zhí)行某種任務(wù)或等待處理某些事件的一個守護(hù)進(jìn)程,與windows下的計劃任務(wù)類似,當(dāng)安裝完成操作系統(tǒng)后,默認(rèn)會安裝此服務(wù) 工具,并且會自動啟動crond進(jìn)程,crond進(jìn)程每分鐘會定期檢查是否有要執(zhí)行的任務(wù),如果有要執(zhí)行的任務(wù),則自動執(zhí)行該任務(wù)。

cron是服務(wù)名稱,crond是后臺進(jìn)程,crontab則是定制好的計劃任務(wù)表。大部分linux系統(tǒng)默認(rèn)都安裝了cron,可以檢查一下。

-- 檢查Crontab工具是否安裝
crontab -l
-- 檢查crond服務(wù)是否啟動
service crond status

-- centos安裝
yum install vixie-cron
yum install crontabs

crontab基本操作命令

-- 列出某個用戶cron服務(wù)的詳細(xì)內(nèi)容
crontab -l
-- 編輯某個用戶的cron服務(wù)
crontab -e 

crontab表達(dá)式格式

{minute} {hour} {day-of-month} {month} {day-of-week} {full-path-to-shell-script}

 minute: 區(qū)間為 0 – 59
 hour: 區(qū)間為0 – 23
 day-of-month: 區(qū)間為0 – 31
 month: 區(qū)間為1 – 12. 1 是1月. 12是12月
 Day-of-week: 區(qū)間為0 – 7. 周日可以是0或7.

在以上各個字段中,還可以使用以下特殊字符:
星號(*):代表所有可能的值,例如month字段如果是星號,則表示在滿足其它字段的制約條件后每月都執(zhí)行該命令操作。
逗號(,):可以用逗號隔開的值指定一個列表范圍,例如,“1,2,5,7,8,9”
中杠(-):可以用整數(shù)之間的中杠表示一個整數(shù)范圍,例如“2-6”表示“2,3,4,5,6”
正斜線(/):可以用正斜線指定時間的間隔頻率,例如“0-23/2”表示每兩小時執(zhí)行一次。同時正斜線可以和星號一起使用,例如*/10,如果用在minute字段,表示每十分鐘執(zhí)行一次。

推薦一個crontab表達(dá)式的校驗(yàn)網(wǎng)站(https://tool.lu/crontab/)

3. Timer和ScheduledExecutorService (java)

Timer是jdk中提供的一個定時器工具,使用的時候會在主線程之外起一個多帶帶的線程執(zhí)行指定的計劃任務(wù),可以指定執(zhí)行一次或者反復(fù)執(zhí)行多次。

//只執(zhí)行一次
public void schedule(TimerTask task, long delay);
public void schedule(TimerTask task, Date time);
//循環(huán)執(zhí)行
// 在循環(huán)執(zhí)行類別中根據(jù)循環(huán)時間間隔又可以分為兩類
public void schedule(TimerTask task, long delay, long period) ;
public void schedule(TimerTask task, Date firstTime, long period) ;
 
public void scheduleAtFixedRate(TimerTask task, long delay, long period)
public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)

TimerTask是一個實(shí)現(xiàn)了Runnable接口的抽象類,代表一個可以被Timer執(zhí)行的任務(wù)。TimerTask類是一個抽象類,由Timer 安排為一次執(zhí)行或重復(fù)執(zhí)行的任務(wù)。它有一個抽象方法run()方法,該方法用于執(zhí)行相應(yīng)計時器任務(wù)要執(zhí)行的操作。因此每一個具體的任務(wù)類都必須繼承TimerTask,然后重寫run()方法。
另外它還有兩個非抽象的方法

-- 取消此計時器任務(wù)
boolean cancel()
-- 返回此任務(wù)最近實(shí)際執(zhí)行的安排執(zhí)行時間
long scheduledExecutionTime()

當(dāng)然,一般使用Timer的比較少,因?yàn)樗娜秉c(diǎn)比較明顯:

單線程,當(dāng)多個timer同時運(yùn)行時,會等上一個執(zhí)行完成,再執(zhí)行下一個。

Timer線程是不會捕獲異常的,如果TimerTask拋出的了未檢查異常則會導(dǎo)致Timer線程終止。

所以一般使用ScheduledExecutorService替代Timer。
ScheduledExecutorService:也是jdk自帶的一個基于線程池設(shè)計的定時任務(wù)類。其每個調(diào)度任務(wù)都會分配到線程池中的一個線程執(zhí)行,所以其任務(wù)是并發(fā)執(zhí)行的,互不影響。

4. SpringTask (spring)

Timer和ScheduledExecutorService都是屬于jdk層面上實(shí)現(xiàn)定時調(diào)度的類,功能還不足以讓我們滿意,那么現(xiàn)在介紹一個比較完善的定時調(diào)度工具 - SpringTask,是Spring提供的,支持注解和配置文件形式,支持crontab表達(dá)式,使用簡單但功能強(qiáng)大。我個人非常喜歡SpringTask,僅僅是因?yàn)橹С謈rontab表達(dá)式。

在springboot里面使用方式非常簡單:

啟動類添加開啟定時調(diào)度的注解 @EnableScheduling

在需要定時執(zhí)行的方法上,增加注解 @Scheduled(cron ="crontab表達(dá)式")

默認(rèn)的簡單的使用步驟只有以上兩步,但是SpringTask的默認(rèn)使用方式也有一些不足:

默認(rèn)線程池的poolsize為1,可以理解為Timer類似的單線程模式。

無法動態(tài)修改crontab表達(dá)式,修改完只能重新部署后,才能生效。

問題1的解決方式,可以通過自定義 TaskExecutor來修改當(dāng)前的線程池。問題2,則可以直接使用 threadPoolTaskScheduler類實(shí)現(xiàn)自定義的定時調(diào)度規(guī)則。

附解決兩個問題的源碼 TaskTimer.class

@Component
public class TaskTimer {

    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;
    @Autowired
    private TaskRepo taskRepo;

    /**
     * ***定時引擎***
     *
     * 實(shí)例化一個線程池任務(wù)調(diào)度類
     * 默認(rèn) ThreadPoolTaskScheduler 的 poolSize 為1,類似于newSingleThreadExecutor 單線程模式,只能執(zhí)行完一個調(diào)度,再執(zhí)行其他調(diào)度
     * 需要自定義擴(kuò)展poolSize,允許一定程度的 多線程并行場景
     *
     * @return
     */
    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.setPoolSize(100);
        threadPoolTaskScheduler.setThreadNamePrefix("Thread - ");
        threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
        threadPoolTaskScheduler.setAwaitTerminationSeconds(60);
        return threadPoolTaskScheduler;
    }

    /**
     * 啟動定時調(diào)度
     * @param taskCode
     * @param cron
     * @param runnable
     * @return
     */
    public boolean start(String taskCode, String cron,Runnable runnable){
        ScheduledFuture currentFuture=taskRepo.findTask(taskCode);
        //已存在的調(diào)度,無法再創(chuàng)建
        if(currentFuture!=null){
            throw  new RuntimeException("調(diào)度""+taskCode+""已存在,無法再創(chuàng)建");
        }
        //創(chuàng)建新的調(diào)度,并加入 taskMap
        currentFuture = threadPoolTaskScheduler.schedule(runnable,new CronTrigger(cron));
        if (currentFuture!=null){
            this.taskRepo.addTask(taskCode,currentFuture);
            return true;
        }
        throw  new RuntimeException("任務(wù)啟動失?。。。?);
    }

    /**
     * 暫停定時調(diào)度
     * @param taskCode
     * @return
     */
    public boolean stop(String taskCode) {
        //taskId 不存在的,無法停止,只能修改
        ScheduledFuture currentFuture=this.taskRepo.findTask(taskCode);
        if(currentFuture!=null){
            return currentFuture.cancel(true);
        }
        return true;
    }

    /**
     * 刪除定時調(diào)度
     * @param taskCode
     * @return
     */
    public boolean remove(String taskCode){
        ScheduledFuture currentFuture=this.taskRepo.findTask(taskCode);
        if(currentFuture!=null){
             currentFuture.cancel(true);
             taskRepo.removeTask(taskCode);
             return true;
        }
        return false;
    }

    /**
     * 修改定時調(diào)度
     * @param taskCode
     * @param cron
     * @param runnable
     * @return
     */
    public boolean update(String taskCode,String cron,Runnable runnable){
        ScheduledFuture currentFuture=this.taskRepo.findTask(taskCode);
        //已存在的定時調(diào)度,先停止,再新增,并更新 新的ScheduledFuture
        if(currentFuture!=null) {
            currentFuture.cancel(true);
        }
        currentFuture= threadPoolTaskScheduler.schedule(runnable,new CronTrigger(cron));
        if(currentFuture!=null){
            this.taskRepo.addTask(taskCode,currentFuture);
            return true;
        }
        return false;
    }

}
5. Quartz (其他產(chǎn)品)

Quartz是一個完全由 Java 編寫的開源作業(yè)調(diào)度框架,為在 Java 應(yīng)用程序中進(jìn)行作業(yè)調(diào)度提供了簡單卻強(qiáng)大的機(jī)制。它是一個功能強(qiáng)大、十分成熟的重量級產(chǎn)品,還支持負(fù)載均衡,實(shí)現(xiàn)分布式調(diào)度。

不過,對于Quartz的安裝你要多花點(diǎn)功夫了,從數(shù)據(jù)庫要建哪些表,到應(yīng)用程序該如何部署。對于這樣一個龐大的產(chǎn)品,本篇文章就不附上它的使用說明書了。

參考文檔

SpringBoot中并發(fā)定時任務(wù)的實(shí)現(xiàn)、動態(tài)定時任務(wù)的實(shí)現(xiàn)

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

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

相關(guān)文章

  • 那些,我們過的定時調(diào)度

    摘要:類是一個抽象類,由安排為一次執(zhí)行或重復(fù)執(zhí)行的任務(wù)。也是自帶的一個基于線程池設(shè)計的定時任務(wù)類。問題,則可以直接使用類實(shí)現(xiàn)自定義的定時調(diào)度規(guī)則。 定時調(diào)度作為后端開發(fā)人員,我們總會遇到這樣的業(yè)務(wù)場景:每周同步一批數(shù)據(jù);每半個小時檢查一遍服務(wù)器運(yùn)行狀況;每天早上八點(diǎn)給用戶發(fā)送一份包含今日待辦事項的郵件,等等。 這些場景中都離不開定時器,就像一個定好時間規(guī)則的鬧鐘,它會在指定時間觸發(fā),執(zhí)行我們...

    The question 評論0 收藏0
  • 那些過的SAP IDE

    摘要:本文里提到的所有都是基于版本的,這使得我又一次被鄙視了使用的程序猿鄙視使用的程序猿。因此這些事物碼本身也是可以通過進(jìn)行增強(qiáng)的。 在Google上根據(jù)關(guān)鍵字程序員鄙視鏈搜索,會得到68多萬條結(jié)果。 showImg(https://segmentfault.com/img/remote/1460000014000687); 玲瑯滿目的搜索結(jié)果里是眾多不同維度劃分的鄙視鏈。 其中有一個維度,...

    denson 評論0 收藏0

發(fā)表評論

0條評論

PrototypeZ

|高級講師

TA的文章

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