springboot下使用定時(shí)任務(wù)的方式全揭秘

1. 線程實(shí)現(xiàn)

利用線程可以設(shè)定休眠時(shí)間的方式可以實(shí)現(xiàn)簡單的定時(shí)任務(wù)邏輯唠雕。

    public static void main(String[] args){
        //定時(shí)任務(wù)間隔時(shí)間
        int sleepTime=2*1000;
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        System.out.println("Thread方式執(zhí)行一次定時(shí)任務(wù)");
                        //線程休眠規(guī)定時(shí)間
                        Thread.sleep(sleepTime);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

2. Timer類

Timer類允許調(diào)度一個TimerTask任務(wù)贸营。使用這種方式可以讓你的程序按照某一個頻度執(zhí)行。

    public static void main(String[] args){
        int sleepTime=2*1000;
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("Timer方式執(zhí)行一次定時(shí)任務(wù)");
            }
        };
        new Timer().schedule(timerTask,1,sleepTime);
    }

3. ScheduledExecutorService類

ScheduledExecutorService,是基于線程池設(shè)計(jì)的定時(shí)任務(wù)類,每個調(diào)度任務(wù)都會分配到線程池中的一個線程去執(zhí)行,也就是說,任務(wù)是并發(fā)執(zhí)行,互不影響岩睁。
因此钞脂,基于ScheduledExecutorService類的定時(shí)任務(wù)類,歸根到底也是基于線程的調(diào)度實(shí)現(xiàn)的捕儒。

    public static void main(String[] args){
        int sleepTime=2*1000;
        ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
        scheduledExecutor.scheduleAtFixedRate(
                new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("ScheduledExecutorService方式執(zhí)行一次定時(shí)任務(wù)");
                    }
                }
        ,1,sleepTime, TimeUnit.SECONDS);
    }

4. 整合Quartz

Quartz是一個完全由Java編寫的開源作業(yè)調(diào)度框架冰啃,為在 Java 應(yīng)用程序中進(jìn)行作業(yè)調(diào)度提供了簡單卻強(qiáng)大的機(jī)制,要理解它的使用方式,需要先理解它的幾個核心概念:

Job: 表示一個工作刘莹,要執(zhí)行的具體內(nèi)容阎毅。此接口中只有一個方法,如下:

void execute(JobExecutionContext context)

JobDetail: 表示一個具體的可執(zhí)行的調(diào)度程序点弯,Job 是這個可執(zhí)行程調(diào)度程序所要執(zhí)行的內(nèi)容扇调,另外 JobDetail 還包含了這個任務(wù)調(diào)度的方案和策略。
Trigger: 代表一個調(diào)度參數(shù)的配置抢肛,什么時(shí)候去調(diào)狼钮。
Scheduler: 代表一個調(diào)度容器碳柱,一個調(diào)度容器中可以注冊多個 JobDetail 和Trigger。當(dāng) Trigger 與 JobDetail 組合熬芜,就可以被 Scheduler 容器調(diào)度了莲镣。
有了這些概念之后,我們就可以把Quartz整合到我們的springboot項(xiàng)目中了猛蔽。

引入quartz依賴

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
配置
@Configuration
public class QuartzConfig {
    @Bean
    public JobDetail quartzDetail(){
        return JobBuilder.newJob(QuartzTest.class).withIdentity("QuartzTest").storeDurably().build();
    }
    @Bean
    public SimpleTrigger quartzTrigger(){
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(10)
                .repeatForever();
        return TriggerBuilder.newTrigger().forJob(quartzDetail())
                .withIdentity("QuartzTest")
                .withSchedule(scheduleBuilder)
                .build();
    }
}
測試
public class QuartzTest extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext){
        System.out.println("quartz執(zhí)行一次定時(shí)任務(wù) ");
    }
}

5. 使用Scheduled注解

@Scheduled是spring為定時(shí)任務(wù)而生的一個注解剥悟,查看注解的源碼:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
//cron表達(dá)式
    String cron() default "";
//接收一個java.util.TimeZone#ID。
    String zone() default "";
//上一次執(zhí)行完畢時(shí)間點(diǎn)之后多長時(shí)間再執(zhí)行
    long fixedDelay() default -1;
//支持占位符形式的字符串類型的fixedDelay
    String fixedDelayString() default "";
//上一次開始執(zhí)行時(shí)間點(diǎn)之后多長時(shí)間再執(zhí)行
    long fixedRate() default -1;
//支持占位符形式的字符串類型的fixedRateString
    String fixedRateString() default "";
//第一次延遲多長時(shí)間后再執(zhí)行    
    long initialDelay() default -1;
//支持占位符形式的字符串類型的initialDelay
    String initialDelayString() default "";
}

可以看出:Scheduled注解中的參數(shù)用來設(shè)置“定時(shí)”動作曼库,通常情況下区岗,比較常用的參數(shù)是cron(),這意味著我們需要學(xué)會一些cron表達(dá)式相關(guān)的語法,但由于內(nèi)容較多毁枯,篇幅較長慈缔,在這里暫不鋪開講解,我們把cron語法相關(guān)放到文章最后种玛,在此先講解如何用Scheduled注解來實(shí)現(xiàn)定時(shí)任務(wù)藐鹤。

開啟定時(shí)任務(wù)支持
@SpringBootApplication
/**
 * 開啟定時(shí)任務(wù)支持
 */
@EnableScheduling
public class TestApplication  extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(this.getClass());
    }
}
使用
@Component
public class ScheduledTest {
    private Logger logger = LoggerFactory.getLogger(ScheduledTest.class);
    /**
     * 每15秒執(zhí)行一次定時(shí)任務(wù)
     */
    @Scheduled(cron = "0/15 * * * * ? ")
    public void testCron(){
        logger.info("Scheduled 執(zhí)行一次定時(shí)任務(wù)");
    }
}

6. cron表達(dá)式

cron表達(dá)式是一個字符串其語法為:

[秒] [分] [小時(shí)] [日] [月] [周] [年]

其中[年]為非必填項(xiàng),因此通常cron表達(dá)式通常由6或7部分內(nèi)容組成赂韵,內(nèi)容的取值為數(shù)字或者一些cron表達(dá)式約定的特殊字符娱节,這些特殊字符稱為“通配符”,每一個通配符分別代指一種值祭示。cron表達(dá)式可以用這樣的表格來表示:



其中通配符的解釋以及作用如下:


示例:
每2秒執(zhí)行一次:0/5 ?
每5分鐘執(zhí)行一次:0 0/5 * ?
1分肄满、12分、45分執(zhí)行一次:0 1,12,45 * ?
每天23點(diǎn)59分59秒執(zhí)行一次:59 59 23 ?
每月15號凌晨3點(diǎn)執(zhí)行一次:0 0 3 15 * ?
每月最后一天12點(diǎn)執(zhí)行一次:0 0 12 L * ?

End

順便在此給大家推薦一個Java方面的交流學(xué)習(xí)群:4112676质涛,里面會分享一些高級面試題稠歉,還有資深架構(gòu)師錄制的視頻錄像:有Spring,MyBatis汇陆,Netty源碼分析怒炸,高并發(fā)、高性能毡代、分布式阅羹、微服務(wù)架構(gòu)的原理,JVM性能優(yōu)化這些成為架構(gòu)師必備的知識體系教寂,主要針對Java開發(fā)人員提升自己灯蝴,突破瓶頸,相信你來學(xué)習(xí)孝宗,會有提升和收獲穷躁。在這個群里會有你需要的內(nèi)容 朋友們請抓緊時(shí)間加入進(jìn)來吧

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子问潭,更是在濱河造成了極大的恐慌猿诸,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狡忙,死亡現(xiàn)場離奇詭異梳虽,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)灾茁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進(jìn)店門窜觉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人北专,你說我怎么就攤上這事禀挫。” “怎么了拓颓?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵语婴,是天一觀的道長。 經(jīng)常有香客問我驶睦,道長砰左,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任场航,我火速辦了婚禮缠导,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘溉痢。我一直安慰自己酬核,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布适室。 她就那樣靜靜地躺著,像睡著了一般举瑰。 火紅的嫁衣襯著肌膚如雪捣辆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天此迅,我揣著相機(jī)與錄音汽畴,去河邊找鬼。 笑死耸序,一個胖子當(dāng)著我的面吹牛忍些,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播坎怪,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼罢坝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了搅窿?” 一聲冷哼從身側(cè)響起嘁酿,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤隙券,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后闹司,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娱仔,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年游桩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了牲迫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡借卧,死狀恐怖盹憎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谓娃,我是刑警寧澤脚乡,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站滨达,受9級特大地震影響奶稠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜捡遍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一锌订、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧画株,春花似錦辆飘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至续挟,卻和暖如春紧卒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背诗祸。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工跑芳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人直颅。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓博个,卻偏偏與公主長得像阀趴,于是被迫代替她去往敵國和親就漾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容