SpringBoot 實(shí)現(xiàn)定時(shí)任務(wù)的方法詳解
一、定時(shí)任務(wù)實(shí)現(xiàn)的幾種方式:
Timer
這是java自帶的java.util.Timer類,這個(gè)類允許你調(diào)度一個(gè)java.util.TimerTask任務(wù)。使用這種方式可以讓你的程序按照某一個(gè)頻度執(zhí)行,但不能在指定時(shí)間運(yùn)行。一般用的較少。
ScheduledExecutorService
也jdk自帶的一個(gè)類;是基于線程池設(shè)計(jì)的定時(shí)任務(wù)類,每個(gè)調(diào)度任務(wù)都會(huì)分配到線程池中的一個(gè)線程去執(zhí)行,也就是說(shuō),任務(wù)是并發(fā)執(zhí)行,互不影響。
Spring Task
Spring3.0以后自帶的task,可以將它看成一個(gè)輕量級(jí)的Quartz,而且使用起來(lái)比Quartz簡(jiǎn)單許多。
Quartz
這是一個(gè)功能比較強(qiáng)大的的調(diào)度器,可以讓你的程序在指定時(shí)間執(zhí)行,也可以按照某一個(gè)頻度執(zhí)行,配置起來(lái)稍顯復(fù)雜。
二、基于SpringBoot的定時(shí)任務(wù)
使用SpringBoot 自帶的定時(shí)任務(wù),只需要添加相應(yīng)的注解就可以實(shí)現(xiàn)
2.1 導(dǎo)入SpringBoot啟動(dòng)包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.1.RELEASE</version> </dependency>
2.2 啟動(dòng)類啟用定時(shí)
在啟動(dòng)類上面加上@EnableScheduling即可開(kāi)啟定時(shí)
@SpringBootApplication
@EnableScheduling // 開(kāi)啟定時(shí)
public class SpringBootDemoTimeTaskApplication {
private static final Logger logger = LoggerFactory.getLogger(SpringBootDemoTimeTaskApplication.class);
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoTimeTaskApplication.class);
logger.info("SpringBootDemoTimeTaskApplication start!");
}
}
2.3 創(chuàng)建定時(shí)任務(wù)實(shí)現(xiàn)類SchedulerTask
@Component
public class SchedulerTask {
private static final Logger logger = LoggerFactory.getLogger(SchedulerTask.class);
/**
* @Scheduled(fixedRate = 6000) :上一次開(kāi)始執(zhí)行時(shí)間點(diǎn)之后6秒再執(zhí)行
* @Scheduled(fixedDelay = 6000) :上一次執(zhí)行完畢時(shí)間點(diǎn)之后6秒再執(zhí)行
* @Scheduled(initialDelay=1000, fixedRate=6000) :第一次延遲1秒后執(zhí)行,之后按fixedRate的規(guī)則每6秒執(zhí)行一次
* @Scheduled(cron=""):詳見(jiàn)cron表達(dá)式http://www.pppet.net/
*/
@Scheduled(fixedRate = 5000)
public void scheduled1() {
logger.info("=====>>>>>使用fixedRate執(zhí)行定時(shí)任務(wù)");
}
@Scheduled(fixedDelay = 10000)
public void scheduled2() {
logger.info("=====>>>>>使用fixedDelay執(zhí)行定時(shí)任務(wù)");
}
@Scheduled(cron="*/6 * * * * ?")
private void scheduled3(){
logger.info("使用cron執(zhí)行定時(shí)任務(wù)");
}
}
運(yùn)行結(jié)果:
2019-03-09 17:33:05.681 INFO 7752 --- [ main] c.v.t.SpringBootDemoTimeTaskApplication : SpringBootDemoTimeTaskApplication start! 2019-03-09 17:33:06.002 INFO 7752 --- [ scheduling-1] cn.van.task.service.SchedulerTask : 使用cron執(zhí)行定時(shí)任務(wù) 2019-03-09 17:33:10.680 INFO 7752 --- [ scheduling-1] cn.van.task.service.SchedulerTask : =====>>>>>使用fixedRate執(zhí)行定時(shí)任務(wù) 2019-03-09 17:33:12.003 INFO 7752 --- [ scheduling-1] cn.van.task.service.SchedulerTask : 使用cron執(zhí)行定時(shí)任務(wù) 2019-03-09 17:33:15.676 INFO 7752 --- [ scheduling-1] cn.van.task.service.SchedulerTask : =====>>>>>使用fixedRate執(zhí)行定時(shí)任務(wù) 2019-03-09 17:33:15.676 INFO 7752 --- [ scheduling-1] cn.van.task.service.SchedulerTask : =====>>>>>使用fixedDelay執(zhí)行定時(shí)任務(wù) 2019-03-09 17:33:18.002 INFO 7752 --- [ scheduling-1] cn.van.task.service.SchedulerTask : 使用cron執(zhí)行定時(shí)任務(wù) 2019-03-09 17:33:20.677 INFO 7752 --- [ scheduling-1] cn.van.task.service.SchedulerTask : =====>>>>>使用fixedRate執(zhí)行定時(shí)任務(wù) 2019-03-09 17:33:24.002 INFO 7752 --- [ scheduling-1] cn.van.task.service.SchedulerTask : 使用cron執(zhí)行定時(shí)任務(wù) 2019-03-09 17:33:25.680 INFO 7752 --- [ scheduling-1] cn.van.task.service.SchedulerTask : =====>>>>>使用fixedRate執(zhí)行定時(shí)任務(wù) 2019-03-09 17:33:25.681 INFO 7752 --- [ scheduling-1] cn.van.task.service.SchedulerTask : =====>>>>>使用fixedDelay執(zhí)行定時(shí)任務(wù) 2019-03-09 17:33:30.005 INFO 7752 --- [ scheduling-1] cn.van.task.service.SchedulerTask : 使用cron執(zhí)行定時(shí)任務(wù) 2019-03-09 17:33:30.680 INFO 7752 --- [ scheduling-1] cn.van.task.service.SchedulerTask : =====>>>>>使用fixedRate執(zhí)行定時(shí)任務(wù) 2019-03-09 17:33:35.680 INFO 7752 --- [ scheduling-1] cn.van.task.service.SchedulerTask : =====>>>>>使用fixedRate執(zhí)行定時(shí)任務(wù) 2019-03-09 17:33:35.682 INFO 7752 --- [ scheduling-1] cn.van.task.service.SchedulerTask : =====>>>>>使用fixedDelay執(zhí)行定時(shí)任務(wù)
2.4 執(zhí)行時(shí)間的配置
在上面的定時(shí)任務(wù)中,我們?cè)诜椒ㄉ鲜褂聾Scheduled注解來(lái)設(shè)置任務(wù)的執(zhí)行時(shí)間,并且使用三種屬性配置方式:
fixedRate:定義一個(gè)按一定頻率執(zhí)行的定時(shí)任務(wù)
fixedDelay:定義一個(gè)按一定頻率執(zhí)行的定時(shí)任務(wù),與上面不同的是,改屬性可以配合initialDelay, 定義該任務(wù)延遲執(zhí)行時(shí)間。
cron:通過(guò)表達(dá)式來(lái)配置任務(wù)執(zhí)行時(shí)間--在線cron表達(dá)式生成器
三、多線程執(zhí)行定時(shí)任務(wù)
SpringBoot定時(shí)任務(wù)默認(rèn)單線程,可以看到三個(gè)定時(shí)任務(wù)都已經(jīng)執(zhí)行,并且使同一個(gè)線程中(scheduling-1)串行執(zhí)行,如果只有一個(gè)定時(shí)任務(wù),這樣做肯定沒(méi)問(wèn)題,當(dāng)定時(shí)任務(wù)增多,如果一個(gè)任務(wù)卡死,會(huì)導(dǎo)致其他任務(wù)也無(wú)法執(zhí)行。
3.1 多線程配置類 AsyncConfig.class
@Configuration // 表明該類是一個(gè)配置類
@EnableAsync // 開(kāi)啟異步事件的支持
public class AsyncConfig {
@Value("${myProps.corePoolSize}")
private int corePoolSize;
@Value("${myProps.maxPoolSize}")
private int maxPoolSize;
@Value("${myProps.queueCapacity}")
private int queueCapacity;
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.initialize();
return executor;
}
}
3.2 配置文件application.yml中添加多線程配置
myProps: corePoolSize: 10 maxPoolSize: 100 queueCapacity: 10
3.3 在定時(shí)任務(wù)的類或者方法上添加@Async
此時(shí),可讓每一個(gè)任務(wù)都是在不同的線程中,啟動(dòng)項(xiàng)目,日志打印如下:
2019-03-11 15:16:54.855 INFO 10782 --- [ main] c.v.t.SpringBootDemoTimeTaskApplication : SpringBootDemoTimeTaskApplication start! 2019-03-11 15:16:55.015 INFO 10782 --- [ taskExecutor-1] cn.van.task.service.SchedulerTask : =====>>>>>使用cron執(zhí)行定時(shí)任務(wù)-1 2019-03-11 15:17:00.002 INFO 10782 --- [ taskExecutor-2] cn.van.task.service.SchedulerTask : =====>>>>>使用cron執(zhí)行定時(shí)任務(wù)-2 2019-03-11 15:17:00.002 INFO 10782 --- [ taskExecutor-3] cn.van.task.service.SchedulerTask : =====>>>>>使用cron執(zhí)行定時(shí)任務(wù)-1 2019-03-11 15:17:05.003 INFO 10782 --- [ taskExecutor-4] cn.van.task.service.SchedulerTask : =====>>>>>使用cron執(zhí)行定時(shí)任務(wù)-1 2019-03-11 15:17:06.005 INFO 10782 --- [ taskExecutor-5] cn.van.task.service.SchedulerTask : =====>>>>>使用cron執(zhí)行定時(shí)任務(wù)-2 2019-03-11 15:17:10.004 INFO 10782 --- [ taskExecutor-6] cn.van.task.service.SchedulerTask : =====>>>>>使用cron執(zhí)行定時(shí)任務(wù)-1 2019-03-11 15:17:12.005 INFO 10782 --- [ taskExecutor-7] cn.van.task.service.SchedulerTask : =====>>>>>使用cron執(zhí)行定時(shí)任務(wù)-2 2019-03-11 15:17:15.006 INFO 10782 --- [ taskExecutor-8] cn.van.task.service.SchedulerTask : =====>>>>>使用cron執(zhí)行定時(shí)任務(wù)-1 2019-03-11 15:17:18.004 INFO 10782 --- [ taskExecutor-9] cn.van.task.service.SchedulerTask : =====>>>>>使用cron執(zhí)行定時(shí)任務(wù)-2 2019-03-11 15:17:20.004 INFO 10782 --- [taskExecutor-10] cn.van.task.service.SchedulerTask : =====>>>>>使用cron執(zhí)行定時(shí)任務(wù)-1
日志打印證明了我的預(yù)測(cè),至此,多線程中執(zhí)行定時(shí)任務(wù)完畢!
四、源碼及其延伸
https://github.com/vanDusty/SpringBoot-Home/tree/master/springboot-demo-list/task-demo
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- SpringBoot實(shí)現(xiàn)定時(shí)任務(wù)和異步調(diào)用
- SpringBoot中并發(fā)定時(shí)任務(wù)的實(shí)現(xiàn)、動(dòng)態(tài)定時(shí)任務(wù)的實(shí)現(xiàn)(看這一篇就夠了)推薦
- SpringBoot與Quartz集成實(shí)現(xiàn)分布式定時(shí)任務(wù)集群的代碼實(shí)例
- Springboot整個(gè)Quartz實(shí)現(xiàn)動(dòng)態(tài)定時(shí)任務(wù)的示例代碼
- Quartz+Spring Boot實(shí)現(xiàn)動(dòng)態(tài)管理定時(shí)任務(wù)
- spring boot整合quartz實(shí)現(xiàn)多個(gè)定時(shí)任務(wù)的方法
- SpringBoot定時(shí)任務(wù)兩種(Spring Schedule 與 Quartz 整合 )實(shí)現(xiàn)方法
相關(guān)文章
簡(jiǎn)述JAVA中堆內(nèi)存與棧內(nèi)存的區(qū)別
這篇文章主要介紹了JAVA中堆內(nèi)存與棧內(nèi)存的區(qū)別,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07
SpringMVC4.3解析器HandlerMethodArgumentResolver接口源碼
這篇文章主要為大家介紹了SpringMVC4.3解析器HandlerMethodArgumentResolver接口源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
.properties文件讀取及占位符${...}替換源碼解析
本篇文章主要介紹了.properties文件讀取及占位符${...}替換源碼解析的相關(guān)知識(shí),具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-05-05
java實(shí)現(xiàn)事件委托模式的實(shí)例詳解
這篇文章主要介紹了java實(shí)現(xiàn)事件委托模式的實(shí)例詳解的相關(guān)資料,這里提供實(shí)例來(lái)說(shuō)明如何實(shí)現(xiàn)改功能,希望能幫助到大家理解這樣的模式,需要的朋友可以參考下2017-08-08
iOS socket網(wǎng)絡(luò)編程實(shí)例詳解
socket是一個(gè)針對(duì)TCP和UDP編程的接口,你可以借助它建立TCP連接等。這篇文章主要介紹了iOS socket網(wǎng)絡(luò)編程 ,需要的朋友可以參考下2017-03-03

