国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - SpringBoot中并發定時任務的實現、動態定時任務的實現(看這一篇就夠了)推薦

SpringBoot中并發定時任務的實現、動態定時任務的實現(看這一篇就夠了)推薦

2021-07-29 11:20會煉鋼的小白龍 Java教程

這篇文章主要介紹了SpringBoot并發定時任務動態定時任務實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

一、在java開發領域,目前可以通過以下幾種方式進行定時任務

1、單機部署模式

timer:jdk中自帶的一個定時調度類,可以簡單的實現按某一頻度進行任務執行。提供的功能比較單一,無法實現復雜的調度任務。
scheduledexecutorservice:也是jdk自帶的一個基于線程池設計的定時任務類。其每個調度任務都會分配到線程池中的一個線程執行,所以其任務是并發執行的,互不影響。
spring task:spring提供的一個任務調度工具,支持注解和配置文件形式,支持cron表達式,使用簡單但功能強大。
quartz:一款功能強大的任務調度器,可以實現較為復雜的調度功能,如每月一號執行、每天凌晨執行、每周五執行等等,還支持分布式調度,就是配置稍顯復雜。

2、分布式集群模式(不多介紹,簡單提一下)

問題:

  1. i、如何解決定時任務的多次執行?
  2. ii、如何解決任務的單點問題,實現任務的故障轉移?

問題i的簡單思考:

  1. 1、固定執行定時任務的機器(可以有效避免多次執行的情況 ,缺點就是單點故障問題)。
  2. 2、借助redis的過期機制和分布式鎖。
  3. 3、借助mysql的鎖機制等。

成熟的解決方案:

1、Quartz:可以去看看這篇文章[Quartz分布式]( http://www.jfrwli.cn/article/88680.html)。
2、elastic-job:(https://github.com/elasticjob/elastic-job-lite)當當開發的彈性分布式任務調度系統,采用zookeeper實現分布式協調,實現任務高可用以及分片。
3、xxl-job:(https://github.com/xuxueli/xxl-job)是大眾點評員發布的分布式任務調度平臺,是一個輕量級分布式任務調度框架。
4、saturn:(https://github.com/vipshop/Saturn) 是唯品會提供一個分布式、容錯和高可用的作業調度服務框架。

二、springtask實現定時任務(這里是基于springboot)

1、簡單的定時任務實現

使用方式:

  1. 使用@enablescheduling注解開啟對定時任務的支持。
  2. 使用@scheduled 注解即可,基于corn、fixedrate、fixeddelay等一些定時策略來實現定時任務。

使用缺點:

  1. 1、多個定時任務使用的是同一個調度線程,所以任務是阻塞執行的,執行效率不高。
  2. 2、其次如果出現任務阻塞,導致一些場景的定時計算沒有實際意義,比如每天12點的一個計算任務被阻塞到1點去執行,會導致結果并非我們想要的。

使用優點:

  1. 1、配置簡單
  2. 2、適用于單個后臺線程執行周期任務,并且保證順序一致執行的場景   

 源碼分析:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//默認使用的調度器
if(this.taskscheduler == null) {
 this.localexecutor = executors.newsinglethreadscheduledexecutor();
 this.taskscheduler = new concurrenttaskscheduler(this.localexecutor);
}
//可以看到singlethreadscheduledexecutor指定的核心線程為1,說白了就是單線程執行
public static scheduledexecutorservice newsinglethreadscheduledexecutor() {
 return new delegatedscheduledexecutorservice
 (new scheduledthreadpoolexecutor(1));
}
//利用了delayedworkqueue延時隊列作為任務的存放隊列,這樣便可以實現任務延遲執行或者定時執行
public scheduledthreadpoolexecutor(int corepoolsize) {
 super(corepoolsize, integer.max_value, 0, nanoseconds,
  new delayedworkqueue());
}

2、實現并發的定時任務

使用方式:

方式一:由1中我們知道之所以定時任務是阻塞執行,是配置的線程池決定的,那就好辦了,換一個不就行了!直接上代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@configuration
 public class scheduledconfig implements schedulingconfigurer {
 
 @autowired
 private taskscheduler mythreadpooltaskscheduler;
 
 @override
 public void configuretasks(scheduledtaskregistrar scheduledtaskregistrar) {
  //簡單粗暴的方式直接指定
  //scheduledtaskregistrar.setscheduler(executors.newscheduledthreadpool(5));
  //也可以自定義的線程池,方便線程的使用與維護,這里不多說了
  scheduledtaskregistrar.settaskscheduler(mythreadpooltaskscheduler);
 }
 }
 
 @bean(name = "mythreadpooltaskscheduler")
 public taskscheduler getmythreadpooltaskscheduler() {
 threadpooltaskscheduler taskscheduler = new threadpooltaskscheduler();
 taskscheduler.setpoolsize(10);
 taskscheduler.setthreadnameprefix("haina-scheduled-");
 taskscheduler.setrejectedexecutionhandler(new threadpoolexecutor.callerrunspolicy());
 //調度器shutdown被調用時等待當前被調度的任務完成
 taskscheduler.setwaitfortaskstocompleteonshutdown(true);
 //等待時長
 taskscheduler.setawaitterminationseconds(60);
 return taskscheduler;
 }

方式二:方式一的本質改變了任務調度器默認使用的線程池,接下來這種是不改變調度器的默認線程池,而是把當前任務交給一個異步線程池去執行

首先使用@enableasync 啟用異步任務
然后在定時任務的方法加上@async即可,默認使用的線程池為simpleasynctaskexecutor(該線程池默認來一個任務創建一個線程,就會不斷創建大量線程,極有可能壓爆服務器內存。當然它有自己的限流機制,這里就不多說了,有興趣的自己翻翻源碼~)
項目中為了更好的控制線程的使用,我們可以自定義我們自己的線程池,使用方式@async("mythreadpool")

廢話太多,直接上代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@scheduled(fixedrate = 1000*10,initialdelay = 1000*20)
@async("mythreadpooltaskexecutor")
//@async
public void scheduledtest02(){
 system.out.println(thread.currentthread().getname()+"--->xxxxx--->"+thread.currentthread().getid());
}
 
//自定義線程池
@bean(name = "mythreadpooltaskexecutor")
public taskexecutor getmythreadpooltaskexecutor() {
 threadpooltaskexecutor taskexecutor = new threadpooltaskexecutor();
 taskexecutor.setcorepoolsize(20);
 taskexecutor.setmaxpoolsize(200);
 taskexecutor.setqueuecapacity(25);
 taskexecutor.setkeepaliveseconds(200);
 taskexecutor.setthreadnameprefix("haina-threadpool-");
 // 線程池對拒絕任務(無線程可用)的處理策略,目前只支持abortpolicy、callerrunspolicy;默認為后者
 taskexecutor.setrejectedexecutionhandler(new threadpoolexecutor.callerrunspolicy());
 //調度器shutdown被調用時等待當前被調度的任務完成
 taskexecutor.setwaitfortaskstocompleteonshutdown(true);
 //等待時長
 taskexecutor.setawaitterminationseconds(60);
 taskexecutor.initialize();
 return taskexecutor;
}

線程池的使用心得(后續有專門文章來探討)

java中提供了threadpoolexecutor和scheduledthreadpoolexecutor,對應與spring中的threadpooltaskexecutor和threadpooltaskscheduler,但是在原有的基礎上增加了新的特性,在spring環境下更容易使用和控制。
使用自定義的線程池能夠避免一些默認線程池造成的內存溢出、阻塞等等問題,更貼合自己的服務特性
使用自定義的線程池便于對項目中線程的管理、維護以及監控。
即便在非spring環境下也不要使用java默認提供的那幾種線程池,坑很多,阿里代碼規約不說了嗎,得相信大廠!!!

三、動態定時任務的實現

問題:
使用@scheduled注解來完成設置定時任務,但是有時候我們往往需要對周期性的時間的設置會做一些改變,或者要動態的啟停一個定時任務,那么這個時候使用此注解就不太方便了,原因在于這個注解中配置的cron表達式必須是常量,那么當我們修改定時參數的時候,就需要停止服務,重新部署。

解決辦法:

方式一:實現schedulingconfigurer接口,重寫configuretasks方法,重新制定trigger,核心方法就是addtriggertask(runnable task, trigger trigger) ,不過需要注意的是,此種方式修改了配置值后,需要在下一次調度結束后,才會更新調度器,并不會在修改配置值時實時更新,實時更新需要在修改配置值時額外增加相關邏輯處理。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@configuration
 public class scheduledconfig implements schedulingconfigurer {
 
 @autowired
 private taskscheduler mythreadpooltaskscheduler;
 
 @override
 public void configuretasks(scheduledtaskregistrar scheduledtaskregistrar) {
  //scheduledtaskregistrar.setscheduler(executors.newscheduledthreadpool(5));
  scheduledtaskregistrar.settaskscheduler(mythreadpooltaskscheduler);
  //可以實現動態調整定時任務的執行頻率
  scheduledtaskregistrar.addtriggertask(
    //1.添加任務內容(runnable)
    () -> system.out.println("cccccccccccccccc--->" + thread.currentthread().getid()),
    //2.設置執行周期(trigger)
    triggercontext -> {
     //2.1 從數據庫動態獲取執行周期
     string cron = "0/2 * * * * ? ";
     //2.2 合法性校驗.
 //     if (stringutils.isempty(cron)) {
 //      // omitted code ..
 //     }
      //2.3 返回執行周期(date)
      return new crontrigger(cron).nextexecutiontime(triggercontext);
     }
   );
 }
 }

方式二:使用threadpooltaskscheduler類可實現動態添加刪除功能,當然也可實現執行頻率的調整

首先,我們要認識下這個調度類,它其實是對java中scheduledthreadpoolexecutor的一個封裝改進后的產物,主要改進有以下幾點:

  1. 1、提供默認配置,因為是scheduledthreadpoolexecutor,所以只有poolsize這一個默認參數。
  2. 2、支持自定義任務,通過傳入trigger參數。
  3. 3、對任務出錯處理進行優化,如果是重復性的任務,不拋出異常,通過日志記錄下來,不影響下次運行,如果是只執行一次的任務,將異常往上拋。

順便說下threadpooltaskexecutor相對于threadpoolexecutor的改進點:

  1. 1、提供默認配置,原生的threadpoolexecutor的除了threadfactory和rejectedexecutionhandler其他沒有默認配置
  2. 2、實現asynclistenabletaskexecutor接口,支持對futuretask添加success和fail的回調,任務成功或失敗的時候回執行對應回調方法。
  3. 3、因為是spring的工具類,所以拋出的rejectedexecutionexception也會被轉換為spring框架的taskrejectedexception異常(這個無所謂)
  4. 4、提供默認threadfactory實現,直接通過參數重載配置

扯了這么多,還是直接上代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
@component
public class dynamictimedtask {
 
 private static final logger logger = loggerfactory.getlogger(dynamictimedtask.class);
 
 //利用創建好的調度類統一管理
 //@autowired
 //@qualifier("mythreadpooltaskscheduler")
 //private threadpooltaskscheduler mythreadpooltaskscheduler;
 
 
 //接受任務的返回結果
 private scheduledfuture<?> future;
 
 @autowired
 private threadpooltaskscheduler threadpooltaskscheduler;
 
 //實例化一個線程池任務調度類,可以使用自定義的threadpooltaskscheduler
 @bean
 public threadpooltaskscheduler threadpooltaskscheduler() {
  threadpooltaskscheduler executor = new threadpooltaskscheduler();
  return new threadpooltaskscheduler();
 }
 
 
 /**
 * 啟動定時任務
 * @return
 */
 public boolean startcron() {
  boolean flag = false;
  //從數據庫動態獲取執行周期
  string cron = "0/2 * * * * ? ";
  future = threadpooltaskscheduler.schedule(new checkmodelfile(),cron);
  if (future!=null){
   flag = true;
   logger.info("定時check訓練模型文件,任務啟動成功!!!");
  }else {
   logger.info("定時check訓練模型文件,任務啟動失敗!!!");
  }
  return flag;
 }
 
 /**
 * 停止定時任務
 * @return
 */
 public boolean stopcron() {
  boolean flag = false;
  if (future != null) {
   boolean cancel = future.cancel(true);
   if (cancel){
    flag = true;
    logger.info("定時check訓練模型文件,任務停止成功!!!");
   }else {
    logger.info("定時check訓練模型文件,任務停止失敗!!!");
   }
  }else {
   flag = true;
   logger.info("定時check訓練模型文件,任務已經停止!!!");
  }
  return flag;
 }
 
 
 class checkmodelfile implements runnable{
 
  @override
  public void run() {
   //編寫你自己的業務邏輯
   system.out.print("模型文件檢查完畢!!!")
  }
 }
 
}

四、總結

到此基于springtask下的定時任務的簡單使用算是差不多了,其中不免有些錯誤的地方,或者理解有偏頗的地方歡迎大家提出來!
基于分布式集群下的定時任務使用,后續有時間再繼續!!!

以上所述是小編給大家介紹的springboot并發定時任務動態定時任務實現詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!

原文鏈接:https://www.cnblogs.com/baixianlong/archive/2019/04/05/10659045.html

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 色综合天天天天做夜夜夜夜做 | 99久久久无码国产精品 | 欧美一区在线看 | 91精品国产综合久久久久久 | 五月天色婷婷视频 | 欧美日韩一区二区电影 | 国产一区二区三区 | 日本久久精品一区 | 国产成人精品一区二区三区四区 | 污片网站 | 91精品国产一区二区三区香蕉 | 99精品欧美一区二区三区综合在线 | 羞羞网址| 国产高清精品在线 | 国产乱码久久久久久一区二区 | 久久久av| 精品久久久久久久久久 | 亚洲免费中文 | 羞羞的视频在线免费观看 | 欧美一区二区最爽乱淫视频免费看 | 无码一区二区三区视频 | 久久亚洲欧美日韩精品专区 | 欧美另类视频在线 | 色站综合 | 久久伊人国产 | 国产亚洲精品精品国产亚洲综合 | 中文字幕1区 | 羞羞网站在线观看 | 亚洲人免费视频 | 国产一区久久 | 日韩欧美在线观看一区二区 | 日韩欧美一区视频 | 日本黄色免费播放 | 国产精品久久久久久久久久免费 | 亚洲国产视频一区 | 精品久久99| 国内成人自拍视频 | 成人福利电影 | 亚洲高清视频在线 | 一级一片在线观看 | 亚洲精品中文字幕在线观看 |