SpringBoot
?是為了簡化?Spring
?應(yīng)用的創(chuàng)建、運行、調(diào)試、部署等一系列問題而誕生的產(chǎn)物,自動裝配的特性讓我們可以更好的關(guān)注業(yè)務(wù)本身而不是外部的XML配置,我們只需遵循規(guī)范,引入相關(guān)的依賴就可以輕易的搭建出一個 WEB 工程
成都創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),蚌山企業(yè)網(wǎng)站建設(shè),蚌山品牌網(wǎng)站建設(shè),網(wǎng)站定制,蚌山網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,蚌山網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。
在我們?nèi)粘i_發(fā)中,經(jīng)常會遇到?數(shù)據(jù)定時增量同步、定時發(fā)送郵件、爬蟲定時抓取 的需求;這時我們可以采用定時任務(wù)
的方式去進行工作…..
定時任務(wù):顧名思義就是在指定/特定的時間進行工作,比如我們的手機鬧鐘,它就是一種定時任務(wù)。
實現(xiàn)方式
Timer:?JDK自帶的java.util.Timer
;通過調(diào)度java.util.TimerTask
的方式?讓程序按照某一個頻度執(zhí)行,但不能在指定時間運行。?一般用的較少。
ScheduledExecutorService:?JDK1.5新增的,位于java.util.concurrent
包中;是基于線程池設(shè)計的定時任務(wù)類,每個調(diào)度任務(wù)都會被分配到線程池中,并發(fā)執(zhí)行,互不影響。
Spring Task:?Spring3.0 以后新增了task
,一個輕量級的Quartz
,功能夠用,用法簡單。
Quartz:?功能最為強大的調(diào)度器,可以讓程序在指定時間執(zhí)行,也可以按照某一個頻度執(zhí)行,它還可以動態(tài)開關(guān),但是配置起來比較復(fù)雜?,F(xiàn)如今開源社區(qū)中已經(jīng)很多基于Quartz 實現(xiàn)的分布式定時任務(wù)項目
(xxl-job、elastic-job)。
基于?Timer
?實現(xiàn)的定時調(diào)度,基本就是手擼代碼,目前應(yīng)用較少,不是很推薦
package com.battcn.timer;
import java.time.LocalDateTime;
import java.util.Timer;
import java.util.TimerTask;
/**
* 基于Timer實現(xiàn)的定時調(diào)度(不推薦,用該方式不如用 ScheduledExecutorService )
*
* @author Levin
* @since 2018/5/29 0029
*/
public class TimerDemo {
public static void main(String[] args) {
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
System.out.println("執(zhí)行任務(wù):" + LocalDateTime.now());
}
};
Timer timer = new Timer();
// timerTask:需要執(zhí)行的任務(wù)
// delay:延遲時間(以毫秒為單位)
// period:間隔時間(以毫秒為單位)
timer.schedule(timerTask, 5000, 3000);
}
}
與Timer
很類似,但它的效果更好,多線程并行處理定時任務(wù)時,Timer
運行多個TimeTask
時,只要其中有一個因任務(wù)報錯沒有捕獲拋出的異常,其它任務(wù)便會自動終止運行,使用 ScheduledExecutorService 則可以規(guī)避這個問題
package com.battcn.scheduled;
import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 基于 ScheduledExecutorService 方式,相對的比 Timer 要好
*
* @author Levin
* @since 2018/5/29 0029
*/
public class ScheduledExecutorServiceDemo {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
// 參數(shù):1、具體執(zhí)行的任務(wù) 2、首次執(zhí)行的延時時間
// 3、任務(wù)執(zhí)行間隔 4、間隔時間單位
service.scheduleAtFixedRate(() -> System.out.println("執(zhí)行任務(wù)A:" + LocalDateTime.now()), 0, 3, TimeUnit.SECONDS);
}
}
在?pom.xml
?中添加?spring-boot-starter-web
?依賴即可,它包含了spring-context
,定時任務(wù)相關(guān)的就屬于這個JAR下的org.springframework.scheduling
包中
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
@Scheduled
?定時任務(wù)的核心
fixedRate
屬性不同的是它是將時間進行了切割。(@Scheduled(cron = "0/5 * * * * *")
任務(wù)將在5、10、15、20...
這種情況下進行工作)@Scheduled(fixedRate = 1000)
?假設(shè)第一次工作時間為2018-05-29 16:58:28
,工作時長為3秒
,那么下次任務(wù)的時候就是2018-05-29 16:58:31
)@Scheduled(fixedDelay = 3000)
?假設(shè)第一次任務(wù)工作時間為2018-05-29 16:54:33
,工作時長為5秒
,那么下次任務(wù)的時間就是2018-05-29 16:54:41
)fixedDelay
關(guān)系密切,配合使用,相輔相成。
@Async
?代表該任務(wù)可以進行異步工作,由原本的串行改為并行
package com.battcn.task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 基于 Spring 自帶的
*
* @author Levin
* @since 2018/5/29 0029
*/
@Component
public class SpringTaskDemo {
private static final Logger log = LoggerFactory.getLogger(SpringTaskDemo.class);
@Async
@Scheduled(cron = "0/1 * * * * *")
public void scheduled1() throws InterruptedException {
Thread.sleep(3000);
log.info("scheduled1 每1秒執(zhí)行一次:{}", LocalDateTime.now());
}
@Scheduled(fixedRate = 1000)
public void scheduled2() throws InterruptedException {
Thread.sleep(3000);
log.info("scheduled2 每1秒執(zhí)行一次:{}", LocalDateTime.now());
}
@Scheduled(fixedDelay = 3000)
public void scheduled3() throws InterruptedException {
Thread.sleep(5000);
log.info("scheduled3 上次執(zhí)行完畢后隔3秒繼續(xù)執(zhí)行:{}", LocalDateTime.now());
}
}
cron表達式在線生成:?http://www.pdtools.net/tools/becron.jsp
@EnableScheduling
?注解表示開啟對@Scheduled
注解的解析;同時new ThreadPoolTaskScheduler()
也是相當(dāng)?shù)年P(guān)鍵,通過閱讀過源碼可以發(fā)現(xiàn)默認情況下的?private volatile int poolSize = 1;
這就導(dǎo)致了多個任務(wù)的情況下容易出現(xiàn)競爭情況(多個任務(wù)的情況下,如果第一個任務(wù)沒執(zhí)行完畢,后續(xù)的任務(wù)將會進入等待狀態(tài))。
@EnableAsync
?注解表示開啟@Async
注解的解析;作用就是將串行化的任務(wù)給并行化了。(@Scheduled(cron = "0/1 * * * * *")
假設(shè)第一次工作時間為2018-05-29 17:30:55
,工作周期為3秒
;如果不加@Async
那么下一次工作時間就是2018-05-29 17:30:59
;如果加了@Async
?下一次工作時間就是2018-05-29 17:30:56
)
package com.battcn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
/**
* @author Levin
*/
@EnableAsync
@EnableScheduling
@SpringBootApplication
public class Chapter15Application {
public static void main(String[] args) {
SpringApplication.run(Chapter15Application.class, args);
}
/**
* 很關(guān)鍵:默認情況下 TaskScheduler 的 poolSize = 1
*
* @return 線程池
*/
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(10);
return taskScheduler;
}
}
完成準(zhǔn)備事項后,啟動Chapter15Application
,觀察日志信息如下
2018-05-29 17:35:51.479 INFO 32640 --- [taskScheduler-1] com.battcn.task.SpringTaskDemo : scheduled2 每1秒執(zhí)行一次:2018-05-29T17:35:51.479
2018-05-29 17:35:52.005 INFO 32640 --- [taskScheduler-3] com.battcn.task.SpringTaskDemo : scheduled1 每1秒執(zhí)行一次:2018-05-29T17:35:52.005
2018-05-29 17:35:53.002 INFO 32640 --- [taskScheduler-5] com.battcn.task.SpringTaskDemo : scheduled1 每1秒執(zhí)行一次:2018-05-29T17:35:53.002
2018-05-29 17:35:53.468 INFO 32640 --- [taskScheduler-2] com.battcn.task.SpringTaskDemo : scheduled3 上次執(zhí)行完畢后隔3秒繼續(xù)執(zhí)行:2018-05-29T17:35:53.468
2018-05-29 17:35:54.002 INFO 32640 --- [taskScheduler-6] com.battcn.task.SpringTaskDemo : scheduled1 每1秒執(zhí)行一次:2018-05-29T17:35:54.002
2018-05-29 17:35:54.479 INFO 32640 --- [taskScheduler-7] com.battcn.task.SpringTaskDemo : scheduled2 每1秒執(zhí)行一次:2018-05-29T17:35:54.479
2018-05-29 17:35:55.002 INFO 32640 --- [taskScheduler-8] com.battcn.task.SpringTaskDemo : scheduled1 每1秒執(zhí)行一次:2018-05-29T17:35:55.002
2018-05-29 17:35:56.001 INFO 32640 --- [taskScheduler-1] com.battcn.task.SpringTaskDemo : scheduled1 每1秒執(zhí)行一次:2018-05-29T17:35:56.001
2018-05-29 17:35:57.001 INFO 32640 --- [taskScheduler-3] com.battcn.task.SpringTaskDemo : scheduled1 每1秒執(zhí)行一次:2018-05-29T17:35:57.001
2018-05-29 17:35:57.479 INFO 32640 --- [taskScheduler-7] com.battcn.task.SpringTaskDemo : scheduled2 每1秒執(zhí)行一次:2018-05-29T17:35:57.479
2018-05-29 17:35:58.003 INFO 32640 --- [taskScheduler-4] com.battcn.task.SpringTaskDemo : scheduled1 每1秒執(zhí)行一次:2018-05-29T17:35:58.003
2018-05-29 17:35:59.001 INFO 32640 --- [taskScheduler-5] com.battcn.task.SpringTaskDemo : scheduled1 每1秒執(zhí)行一次:2018-05-29T17:35:59.001
2018-05-29 17:36:00.002 INFO 32640 --- [taskScheduler-6] com.battcn.task.SpringTaskDemo : scheduled1 每1秒執(zhí)行一次:2018-05-29T17:36:00.002
2018-05-29 17:36:00.480 INFO 32640 --- [taskScheduler-7] com.battcn.task.SpringTaskDemo : scheduled2 每1秒執(zhí)行一次:2018-05-29T17:36:00.480
2018-05-29 17:36:01.001 INFO 32640 --- [taskScheduler-8] com.battcn.task.SpringTaskDemo : scheduled1 每1秒執(zhí)行一次:2018-05-29T17:36:01.001
2018-05-29 17:36:01.470 INFO 32640 --- [taskScheduler-9] com.battcn.task.SpringTaskDemo : scheduled3 上次執(zhí)行完畢后隔3秒繼續(xù)執(zhí)行:2018-05-29T17:36:01.470
目前很多大佬都寫過關(guān)于?SpringBoot?的教程了,如有雷同,請多多包涵,本教程基于最新的?spring-boot-starter-parent:2.0.2.RELEASE
編寫,包括新版本的特性都會一起介紹…
本文的重點是你有沒有收獲與成長,其余的都不重要,希望讀者們能謹記這一點。同時我經(jīng)過多年的收藏目前也算收集到了一套完整的學(xué)習(xí)資料,包括但不限于:分布式架構(gòu)、高可擴展、高性能、高并發(fā)、Jvm性能調(diào)優(yōu)、Spring,MyBatis,Nginx源碼分析,redis,ActiveMQ、Mycat、Netty、Kafka、MySQL、Zookeeper、Tomcat、Docker、Dubbo、Nginx等多個知識點高級進階干貨,希望對想成為架構(gòu)師的朋友有一定的參考和幫助
分享文章:SpringBoot:定時任務(wù)詳解
URL網(wǎng)址:http://chinadenli.net/article30/gisopo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開發(fā)、網(wǎng)站制作、關(guān)鍵詞優(yōu)化、面包屑導(dǎo)航、品牌網(wǎng)站建設(shè)、App設(shè)計
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)