成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

3分鐘帶你搞定Spring Boot中Schedule

開發(fā) 前端
實(shí)際的業(yè)務(wù)開發(fā)過程中,我們經(jīng)常會需要定時(shí)任務(wù)來幫助我們完成一些工作,例如每天早上 6 點(diǎn)生成銷售報(bào)表、每晚 23 點(diǎn)清理臟數(shù)據(jù)等等。

[[358511]]

 本文轉(zhuǎn)載自微信公眾號「Java極客技術(shù)」,作者鴨血粉絲。轉(zhuǎn)載本文請聯(lián)系Java極客技術(shù)公眾號。

一、摘要

閱讀完本文大概需要3分鐘,本文主要分享內(nèi)容如下:

  • SpringBoot Schedule 實(shí)踐介紹

二、介紹

在實(shí)際的業(yè)務(wù)開發(fā)過程中,我們經(jīng)常會需要定時(shí)任務(wù)來幫助我們完成一些工作,例如每天早上 6 點(diǎn)生成銷售報(bào)表、每晚 23 點(diǎn)清理臟數(shù)據(jù)等等。

如果你當(dāng)前使用的是 SpringBoot 來開發(fā)項(xiàng)目,那么完成這些任務(wù)會非常容易!

SpringBoot 默認(rèn)已經(jīng)幫我們完成了相關(guān)定時(shí)任務(wù)組件的配置,我們只需要添加相應(yīng)的注解@Scheduled就可以實(shí)現(xiàn)任務(wù)調(diào)度!

三、Schedule 實(shí)踐

3.1、pom 包配置

pom包里面只需要引入Spring Boot Starter包即可!

  1. <dependencies> 
  2.     <!--spring boot核心--> 
  3.     <dependency> 
  4.         <groupId>org.springframework.boot</groupId> 
  5.         <artifactId>spring-boot-starter</artifactId> 
  6.     </dependency> 
  7.     <!--spring boot 測試--> 
  8.     <dependency> 
  9.         <groupId>org.springframework.boot</groupId> 
  10.         <artifactId>spring-boot-starter-test</artifactId> 
  11.         <scope>test</scope> 
  12.     </dependency> 
  13. </dependencies> 

3.2、啟動(dòng)類啟用定時(shí)調(diào)度

在啟動(dòng)類上面加上@EnableScheduling即可開啟定時(shí)

  1. @SpringBootApplication 
  2. @EnableScheduling 
  3. public class ScheduleApplication { 
  4.  
  5.     public static void main(String[] args) { 
  6.         SpringApplication.run(ScheduleApplication.class, args); 
  7.     } 

3.3、創(chuàng)建定時(shí)任務(wù)

Spring Scheduler支持四種形式的任務(wù)調(diào)度!

  • fixedRate:固定速率執(zhí)行,例如每5秒執(zhí)行一次
  • fixedDelay:固定延遲執(zhí)行,例如距離上一次調(diào)用成功后2秒執(zhí)行
  • initialDelay:初始延遲任務(wù),例如任務(wù)開啟過5秒后再執(zhí)行,之后以固定頻率或者間隔執(zhí)行
  • cron:使用 Cron 表達(dá)式執(zhí)行定時(shí)任務(wù)

3.3.1、固定速率執(zhí)行

你可以通過使用fixedRate參數(shù)以固定時(shí)間間隔來執(zhí)行任務(wù),示例如下:

  1. @Component 
  2. public class SchedulerTask { 
  3.  
  4.     private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class); 
  5.     private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
  6.  
  7.     /** 
  8.   * fixedRate:固定速率執(zhí)行。每5秒執(zhí)行一次。 
  9.   */ 
  10.  @Scheduled(fixedRate = 5000) 
  11.  public void runWithFixedRate() { 
  12.      log.info("Fixed Rate Task,Current Thread : {},The time is now : {}", Thread.currentThread().getName(), dateFormat.format(new Date())); 
  13.  } 

運(yùn)行ScheduleApplication主程序,即可看到控制臺輸出效果:

  1. Fixed Rate Task,Current Thread : scheduled-thread-1,The time is now : 2020-12-15 11:46:00 
  2. Fixed Rate Task,Current Thread : scheduled-thread-1,The time is now : 2020-12-15 11:46:10 
  3. ... 

3.3.2、固定延遲執(zhí)行

你可以通過使用fixedDelay參數(shù)來設(shè)置上一次任務(wù)調(diào)用完成與下一次任務(wù)調(diào)用開始之間的延遲時(shí)間,示例如下:

  1. @Component 
  2. public class SchedulerTask { 
  3.  
  4.     private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class); 
  5.     private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
  6.  
  7.     /** 
  8.      * fixedDelay:固定延遲執(zhí)行。距離上一次調(diào)用成功后2秒后再執(zhí)行。 
  9.      */ 
  10.     @Scheduled(fixedDelay = 2000) 
  11.     public void runWithFixedDelay() { 
  12.         log.info("Fixed Delay Task,Current Thread : {},The time is now : {}", Thread.currentThread().getName(), dateFormat.format(new Date())); 
  13.     } 

控制臺輸出效果:

  1. Fixed Delay Task,Current Thread : scheduled-thread-1,The time is now : 2020-12-15 11:46:00 
  2. Fixed Delay Task,Current Thread : scheduled-thread-1,The time is now : 2020-12-15 11:46:02 
  3. ... 

3.3.3、初始延遲任務(wù)

你可以通過使用initialDelay參數(shù)與fixedRate或者fixedDelay搭配使用來實(shí)現(xiàn)初始延遲任務(wù)調(diào)度。

  1. @Component 
  2. public class SchedulerTask { 
  3.  
  4.     private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class); 
  5.     private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
  6.  
  7.  /** 
  8.      * initialDelay:初始延遲。任務(wù)的第一次執(zhí)行將延遲5秒,然后將以5秒的固定間隔執(zhí)行。 
  9.      */ 
  10.     @Scheduled(initialDelay = 5000, fixedRate = 5000) 
  11.     public void reportCurrentTimeWithInitialDelay() { 
  12.         log.info("Fixed Rate Task with Initial Delay,Current Thread : {},The time is now : {}", Thread.currentThread().getName(), dateFormat.format(new Date())); 
  13.     } 

控制臺輸出效果:

  1. Fixed Rate Task with Initial Delay,Current Thread : scheduled-thread-1,The time is now : 2020-12-15 11:46:05 
  2. Fixed Rate Task with Initial Delay,Current Thread : scheduled-thread-1,The time is now : 2020-12-15 11:46:10 
  3. ... 

3.3.4、使用 Cron 表達(dá)式

Spring Scheduler同樣支持Cron表達(dá)式,如果以上簡單參數(shù)都不能滿足現(xiàn)有的需求,可以使用 cron 表達(dá)式來定時(shí)執(zhí)行任務(wù)。

關(guān)于cron表達(dá)式的具體用法,可以點(diǎn)擊參考這里:https://cron.qqe2.com/

  1. @Component 
  2. public class SchedulerTask { 
  3.  
  4.     private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class); 
  5.     private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
  6.  
  7.     /** 
  8.      * cron:使用Cron表達(dá)式。每6秒中執(zhí)行一次 
  9.      */ 
  10.     @Scheduled(cron = "*/6 * * * * ?"
  11.     public void reportCurrentTimeWithCronExpression() { 
  12.         log.info("Cron Expression,Current Thread : {},The time is now : {}", Thread.currentThread().getName(), dateFormat.format(new Date())); 
  13.     } 

控制臺輸出效果:

  1. Cron Expression,Current Thread : scheduled-thread-1,The time is now : 2020-12-15 11:46:06 
  2. Cron Expression,Current Thread : scheduled-thread-1,The time is now : 2020-12-15 11:46:12 
  3. ... 

3.4、異步執(zhí)行定時(shí)任務(wù)

在介紹異步執(zhí)行定時(shí)任務(wù)之前,我們先看一個(gè)例子!

在下面的示例中,我們創(chuàng)建了一個(gè)每隔2秒執(zhí)行一次的定時(shí)任務(wù),在任務(wù)里面大概需要花費(fèi) 3 秒鐘,猜猜執(zhí)行結(jié)果如何?

  1. @Component 
  2. public class AsyncScheduledTask { 
  3.  
  4.     private static final Logger log = LoggerFactory.getLogger(AsyncScheduledTask.class); 
  5.     private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
  6.  
  7.     @Scheduled(fixedRate = 2000) 
  8.     public void runWithFixedDelay() { 
  9.         try { 
  10.             TimeUnit.SECONDS.sleep(3); 
  11.             log.info("Fixed Delay Task, Current Thread : {} : The time is now {}", Thread.currentThread().getName(), dateFormat.format(new Date())); 
  12.         } catch (InterruptedException e) { 
  13.             log.error("錯(cuò)誤信息",e); 
  14.         } 
  15.     } 

控制臺輸入結(jié)果:

  1. Fixed Delay Task, Current Thread : scheduling-1 : The time is now 2020-12-15 17:55:26 
  2. Fixed Delay Task, Current Thread : scheduling-1 : The time is now 2020-12-15 17:55:31 
  3. Fixed Delay Task, Current Thread : scheduling-1 : The time is now 2020-12-15 17:55:36 
  4. Fixed Delay Task, Current Thread : scheduling-1 : The time is now 2020-12-15 17:55:41 
  5. ... 

很清晰的看到,任務(wù)調(diào)度頻率變成了每隔5秒調(diào)度一次!

這是為啥呢?

從Current Thread : scheduling-1輸出結(jié)果可以很看到,任務(wù)執(zhí)行都是同一個(gè)線程!默認(rèn)的情況下,@Scheduled任務(wù)都在 Spring 創(chuàng)建的大小為 1 的默認(rèn)線程池中執(zhí)行!

更直觀的結(jié)果是,任務(wù)都是串行執(zhí)行!

下面,我們將其改成異步線程來執(zhí)行,看看效果如何?

  1. @Component 
  2. @EnableAsync 
  3. public class AsyncScheduledTask { 
  4.  
  5.     private static final Logger log = LoggerFactory.getLogger(AsyncScheduledTask.class); 
  6.     private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
  7.  
  8.  
  9.     @Async 
  10.     @Scheduled(fixedDelay = 2000) 
  11.     public void runWithFixedDelay() { 
  12.         try { 
  13.             TimeUnit.SECONDS.sleep(3); 
  14.             log.info("Fixed Delay Task, Current Thread : {} : The time is now {}", Thread.currentThread().getName(), dateFormat.format(new Date())); 
  15.         } catch (InterruptedException e) { 
  16.             log.error("錯(cuò)誤信息",e); 
  17.         } 
  18.     } 

控制臺輸出結(jié)果:

  1. Fixed Delay Task, Current Thread : SimpleAsyncTaskExecutor-1 : The time is now 2020-12-15 18:55:26 
  2. Fixed Delay Task, Current Thread : SimpleAsyncTaskExecutor-2 : The time is now 2020-12-15 18:55:28 
  3. Fixed Delay Task, Current Thread : SimpleAsyncTaskExecutor-3 : The time is now 2020-12-15 18:55:30 
  4. ... 

任務(wù)的執(zhí)行頻率不受方法內(nèi)的時(shí)間影響,以并行方式執(zhí)行!

3.5、自定義任務(wù)線程池

雖然默認(rèn)的情況下,@Scheduled任務(wù)都在 Spring 創(chuàng)建的大小為 1 的默認(rèn)線程池中執(zhí)行,但是我們也可以自定義線程池,只需要實(shí)現(xiàn)SchedulingConfigurer類即可!

自定義線程池示例如下:

  1. @Configuration 
  2. public class SchedulerConfig implements SchedulingConfigurer { 
  3.  
  4.     @Override 
  5.     public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { 
  6.         ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); 
  7.         //線程池大小為10 
  8.         threadPoolTaskScheduler.setPoolSize(10); 
  9.         //設(shè)置線程名稱前綴 
  10.         threadPoolTaskScheduler.setThreadNamePrefix("scheduled-thread-"); 
  11.         //設(shè)置線程池關(guān)閉的時(shí)候等待所有任務(wù)都完成再繼續(xù)銷毀其他的Bean 
  12.         threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true); 
  13.         //設(shè)置線程池中任務(wù)的等待時(shí)間,如果超過這個(gè)時(shí)候還沒有銷毀就強(qiáng)制銷毀,以確保應(yīng)用最后能夠被關(guān)閉,而不是阻塞住 
  14.         threadPoolTaskScheduler.setAwaitTerminationSeconds(60); 
  15.         //這里采用了CallerRunsPolicy策略,當(dāng)線程池沒有處理能力的時(shí)候,該策略會直接在 execute 方法的調(diào)用線程中運(yùn)行被拒絕的任務(wù);如果執(zhí)行程序已關(guān)閉,則會丟棄該任務(wù) 
  16.         threadPoolTaskScheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); 
  17.         threadPoolTaskScheduler.initialize(); 
  18.  
  19.         scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler); 
  20.     } 

我們啟動(dòng)服務(wù),看看cron任務(wù)示例調(diào)度效果:

  1. Cron Expression,Current Thread : scheduled-thread-1,The time is now : 2020-12-15 20:46:00 
  2. Cron Expression,Current Thread : scheduled-thread-2,The time is now : 2020-12-15 20:46:06 
  3. Cron Expression,Current Thread : scheduled-thread-3,The time is now : 2020-12-15 20:46:12 
  4. Cron Expression,Current Thread : scheduled-thread-4,The time is now : 2020-12-15 20:46:18 
  5. .... 

當(dāng)前線程名稱已經(jīng)被改成自定義scheduled-thread的前綴!

四、小結(jié)

本文主要圍繞Spring scheduled應(yīng)用實(shí)踐進(jìn)行分享,如果是單體應(yīng)用,使用SpringBoot內(nèi)置的@scheduled注解可以解決大部分業(yè)務(wù)需求,上手非常容易!

五、參考

1、SpringBoot @Schedule使用與原理分析

原文鏈接:https://mp.weixin.qq.com/s/7J1tlZab2oE-6cm6GZiU_w

 

責(zé)任編輯:武曉燕 來源: Java極客技術(shù)
相關(guān)推薦

2020-09-14 11:30:26

HTTP3運(yùn)維互聯(lián)網(wǎng)

2021-06-18 07:34:12

Kafka中間件微服務(wù)

2022-02-16 19:42:25

Spring配置開發(fā)

2010-03-05 17:28:08

2011-05-26 09:03:17

JSONjavascript

2013-06-24 15:32:41

JPush極光推送Android Pus移動(dòng)開發(fā)

2017-08-10 13:13:44

Linux正則表達(dá)式

2025-03-13 06:22:59

2022-06-17 08:05:28

Grafana監(jiān)控儀表盤系統(tǒng)

2021-12-02 06:58:03

AIOps通信服務(wù)

2021-12-01 06:50:50

Docker底層原理

2021-10-19 07:27:08

HTTP代理網(wǎng)絡(luò)

2020-10-13 18:22:58

DevOps工具開發(fā)

2023-10-09 16:35:19

方案Spring支付

2024-12-13 15:29:57

SpringSpringBeanJava

2019-11-22 11:10:26

區(qū)塊鏈技術(shù)

2021-08-03 17:00:25

Spring Boot代碼Java

2025-03-18 09:20:00

Go語言Golang

2009-11-26 11:19:52

NIS服務(wù)器

2025-06-12 07:32:49

Spring框架SRS
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 午夜影院中文字幕 | 精品福利av导航 | 精品中文字幕一区二区 | 久久精品影视 | 久久久久国产一区二区三区四区 | 一区二区三区四区不卡 | 亚洲国产精品久久 | 欧美三级免费观看 | 日韩欧美一区在线 | 日韩精品在线网站 | 在线激情视频 | 欧美福利网站 | 97精品超碰一区二区三区 | 亚洲三级在线 | 波多野结衣一区二区 | 亚洲精品一区二三区不卡 | 精品一二区 | 日韩成人免费中文字幕 | 成人午夜免费视频 | 很很干很很日 | 国产一区二区影院 | 91社影院在线观看 | 天天操天天操 | 午夜不卡福利视频 | 欧美一区永久视频免费观看 | 天天曰夜夜 | 一级大片 | 国产成人精品久久二区二区91 | av中文天堂 | 91综合网 | 中文一区| 天天夜夜操 | 一区二区三区四区在线 | 国产成人综合av | 日韩欧美一区二区三区在线播放 | 亚洲成人第一页 | 国产 日韩 欧美 在线 | 国产精品二区三区在线观看 | 国产精品成人一区二区 | 超碰97免费在线 | 国产精品a免费一区久久电影 |