SprintBoot實現定時任務

SprintBoot實現定時任務

TestApplication.kt

@SpringBootApplication
@EnableScheduling //此註解表示自動配置定時任務
@ComponentScan("schedule")
open class TestApplication {
}

fun main(args: Array<String>) {
    SpringApplication.run(TestApplication::class.kotlin, *args)
}

TestSchedule.kt

@Component
class Job {
    @Scheduled(cron = "\${job.one.cron}")
    fun run1() {
        repeat(10) {

            println("${Thread.currentThread().name} job1 hello")
            Thread.sleep(1000);
        }

    }

    @Scheduled(cron = "\${job.two.cron}")
    fun run2() {
        repeat(10) {
            println("${Thread.currentThread().name} job2 hello")
            Thread.sleep(1000);
        }
    }
}

application.properties

job.one.cron=* * * * * ?
job.two.cron=* * * * * ?

輸出

pool-1-thread-1 job1 hello
pool-1-thread-1 job1 hello
pool-1-thread-1 job1 hello
pool-1-thread-1 job1 hello
pool-1-thread-1 job1 hello
pool-1-thread-1 job1 hello
pool-1-thread-1 job1 hello
pool-1-thread-1 job1 hello
pool-1-thread-1 job1 hello
pool-1-thread-1 job1 hello
pool-1-thread-1 job2 hello
pool-1-thread-1 job2 hello
pool-1-thread-1 job2 hello
pool-1-thread-1 job2 hello
pool-1-thread-1 job2 hello
pool-1-thread-1 job2 hello
pool-1-thread-1 job2 hello
pool-1-thread-1 job2 hello
pool-1-thread-1 job2 hello
pool-1-thread-1 job2 hello

總結

上面的代碼可以實現定時任務:每秒運行

但有個問題便是,默認爲單線程執行所有的任務,這樣可能達不到實際定時的效果

多線程執行

如果想要多線程執行定時任務,可以配置一個線程池,這樣定時任務就會去線程池中拿線程執行定時任務了

我們把Application代碼改一下:

@SpringBootApplication
@EnableScheduling
@ComponentScan("schedule")
@Import(ScheduleConfig::class)
open class TestApplication {
}

fun main(args: Array<String>) {
    SpringApplication.run(TestApplication::class.java, *args)
}

並且添加一個ScheduleConfig配置代碼

class ScheduleConfig : SchedulingConfigurer {
    override fun configureTasks(taskRegistrar: ScheduledTaskRegistrar?) {
        taskRegistrar?.setScheduler(Executors.newScheduledThreadPool(10))
    }
}

運行效果:

pool-1-thread-1 job2 hello
pool-1-thread-2 job1 hello
pool-1-thread-2 job1 hello
pool-1-thread-1 job2 hello
pool-1-thread-2 job1 hello
pool-1-thread-1 job2 hello
pool-1-thread-2 job1 hello
pool-1-thread-1 job2 hello
pool-1-thread-2 job1 hello
pool-1-thread-1 job2 hello
pool-1-thread-2 job1 hello
pool-1-thread-1 job2 hello
pool-1-thread-2 job1 hello
pool-1-thread-1 job2 hello
pool-1-thread-2 job1 hello
pool-1-thread-1 job2 hello
pool-1-thread-2 job1 hello
pool-1-thread-1 job2 hello
pool-1-thread-2 job1 hello

由輸出,我們看出,確實由多個線程執行了定時任務。

Scheduled

我們來看下這個註解可以方什麼東西進去:

public @interface Scheduled {

    /**
     * A cron-like expression, extending the usual UN*X definition to include
     * triggers on the second as well as minute, hour, day of month, month
     * and day of week.  e.g. {@code "0 * * * * MON-FRI"} means once per minute on
     * weekdays (at the top of the minute - the 0th second).
     * @return an expression that can be parsed to a cron schedule
     * @see org.springframework.scheduling.support.CronSequenceGenerator
     */
    String cron() default "";

    /**
     * A time zone for which the cron expression will be resolved. By default, this
     * attribute is the empty String (i.e. the server's local time zone will be used).
     * @return a zone id accepted by {@link java.util.TimeZone#getTimeZone(String)},
     * or an empty String to indicate the server's default time zone
     * @since 4.0
     * @see org.springframework.scheduling.support.CronTrigger#CronTrigger(String, java.util.TimeZone)
     * @see java.util.TimeZone
     */
    String zone() default "";

    /**
     * Execute the annotated method with a fixed period in milliseconds between the
     * end of the last invocation and the start of the next.
     * @return the delay in milliseconds
     */
    long fixedDelay() default -1;

    /**
     * Execute the annotated method with a fixed period in milliseconds between the
     * end of the last invocation and the start of the next.
     * @return the delay in milliseconds as a String value, e.g. a placeholder
     * @since 3.2.2
     */
    String fixedDelayString() default "";

    /**
     * Execute the annotated method with a fixed period in milliseconds between
     * invocations.
     * @return the period in milliseconds
     */
    long fixedRate() default -1;

    /**
     * Execute the annotated method with a fixed period in milliseconds between
     * invocations.
     * @return the period in milliseconds as a String value, e.g. a placeholder
     * @since 3.2.2
     */
    String fixedRateString() default "";

    /**
     * Number of milliseconds to delay before the first execution of a
     * {@link #fixedRate()} or {@link #fixedDelay()} task.
     * @return the initial delay in milliseconds
     * @since 3.2
     */
    long initialDelay() default -1;

    /**
     * Number of milliseconds to delay before the first execution of a
     * {@link #fixedRate()} or {@link #fixedDelay()} task.
     * @return the initial delay in milliseconds as a String value, e.g. a placeholder
     * @since 3.2.2
     */
    String initialDelayString() default "";

}
  • cron cron表達式
  • zone cron表達式使用的時區,默認是local zone
  • fixedDelay 每次任務啓動時的間隔時間
  • fixedDelayStringfixedDelay 一樣,不過這個是string
  • fixedRate 上次任務結束後間隔多少時間再啓動下一次任務,這樣避免前一個任務尚未結束又啓動下一個任務
  • fixedRateString 同理
  • initialDelay 程序啓動後至任務首次執行時的間隔
  • initialDelayString 同理

Cron 表達式

cron 表達式有六個區域(5個空格)或者 七個區域(6個空格)

Seconds Minutes Hours DayofMonth Month DayofWeek
多少秒 多少分 多少時 一個月第幾天 第幾個月 一週第幾天
Seconds Minutes Hours DayofMonth Month DayofWeek Year
多少秒 多少分 多少時 一個月第幾天 第幾個月 一週第幾天 几几年

  • seconds: , - / * [0-59]
  • minutes: , - / * [0-59]
  • hours: , - / * [0-23]
  • dayofmonth: , - / * ? L W C [0-31]
  • month: , - / * [1-12/JAN-DEC]
  • dayofweek: `, - / * ? L C # [1-12/SUN-SAT]“
  • year : , - / * [1970-2099]

  • * 表示任意值 * * * * * ? 每秒都執行一次

  • ? 表示任意值,只能用在dayofmonth/dayofweek中,因爲這兩個值是互相影響的,比如0 0 0 3 * ?代表每個月的第三天觸發
  • - 表示範圍值 0 5-10 * * * ? 表示任何時間的5分-10分,每分鐘觸發一次
  • / 表示開始時間,和相隔時間 * 5/10 * * * ? 表示每小時 5,15,25,35,45,55 各觸發一次
  • , 表示枚舉 0 1,15 * * * ? 表示每小時第1分和第5分觸發一次
  • L 表示最後一個 0 0 0 3L * ? 表示每年最後一個月的第三天觸發
  • W 有效工作日 0 0 0 ? * LW 表示每個月的最後一週的週五觸發
  • # 用於確定每個月第幾個星期幾 0 0 0 ? * 4#2 表示每個月的第二個星期三觸發

在網上找了些例子,供大家熟悉

0 0 10,14,16 * * ? 每天上午10點,下午2點,40 0/30 9-17 * * ?   朝九晚五工作時間內每半小時
0 0 12 ? * WED 表示每個星期三中午12"0 0 12 * * ?" 每天中午12點觸發
"0 15 10 ? * *" 每天上午10:15觸發
"0 15 10 * * ?" 每天上午10:15觸發
"0 15 10 * * ? *" 每天上午10:15觸發
"0 15 10 * * ? 2005" 2005年的每天上午10:15觸發
"0 * 14 * * ?" 在每天下午2點到下午2:59期間的每1分鐘觸發
"0 0/5 14 * * ?" 在每天下午2點到下午2:55期間的每5分鐘觸發
"0 0/5 14,18 * * ?" 在每天下午2點到2:55期間和下午6點到6:55期間的每5分鐘觸發
"0 0-5 14 * * ?" 在每天下午2點到下午2:05期間的每1分鐘觸發
"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:102:44觸發
"0 15 10 ? * MON-FRI" 週一至週五的上午10:15觸發
"0 15 10 15 * ?" 每月15日上午10:15觸發
"0 15 10 L * ?" 每月最後一日的上午10:15觸發
"0 15 10 ? * 6L" 每月的最後一個星期五上午10:15觸發
"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最後一個星期五上午10:15觸發
"0 15 10 ? * 6#3" 每月的第三個星期五上午10:15觸發

參考

Spring 定時任務(Schedule) 和線程
spring cron表達式
原文出自GC Blog

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章