スケジュールされたタスクの基本的な使用ガイド (cron 時間式、Spring 独自のスケジューラー、JDK ネイティブ タイマー)

cron 時間式 (7 つの部分式)

cron 式は、time 式 (7 つのサブ式) とも呼ばれ、5 または 6 個のスペースで区切られた文字列であり、文字列は 6 または 7 つのドメインに分割され、それぞれが異なる意味を表します。

// 从左到右分别表示:秒 分 时 日 月 周 年;参数以空格隔开,其中 年 不是必须参数,可以省略。
{
    
    Seconds} {
    
    Minutes} {
    
    Hours} {
    
    DayofMonth} {
    
    Month} {
    
    DayofWeek} {
    
    Year}
シリアルナンバー 時間要素 必要ですか? 入力範囲 ワイルドカードを入力できます
1 2番 はい 0-59 、 - * /
2 はい 0-59 、 - * /
3 時間 はい 0-23 、 - * /
4 はい 1-31 、 - * ? /LW
5 はい 1 ~ 12 日または 1 月 ~ 12 月 、 - * /
6 週(月曜日~日曜日) はい 1-7(1=SUN )
或 SUN,MON,TUE,WED,THU,FRI,SAT
、 - * ? /L#
8 いいえ 1970 ~ 2099 年 、 - * /

一般的なワイルドカード:

*	表示匹配该域的任意值,比如 Minutes 域使用 * 表示每分钟都会触发
-	表示范围,比如 Minutes 域使用 10-20 表示从10分钟到20分钟每分钟都会触发一次
,	表示列出枚举值,比如 Minutes 域使用 1,3 表示1分钟和3分钟都会触发一次
/	表示间隔时间触发(开始时间/时间间隔),例如在 Minutes 域使用 5/10 表示从第5分钟开始,每隔10分钟触发一次
?	表示不指定值,简单理解就是忽略该字段的值,直接根据另一个字段的值触发执行,仅被用于 DayofMonth 域和 DayofWeek 域中
    当这两个域其中之一被指定了值以后,为了避免冲突,需要将另一个域的值设为“?L	表示最后,是单词"last"的缩写(最后一天或最后一个星期几);仅被用于 DayofMonth 域和 DayofWeek 域中
    	用在 DayofMonth 域 表示该月的最后一天
    	用在 DayofWeek 域 表示一个星期的最后一天,也就是周六
    在使用'L'时,不要指定列表','或范围'-',否则易导致出现意料之外的结果
	如果在“L”前有具体的内容,它就具有其他的含义了
		例如:“6L”表示这个月的倒数第6天,“FRIL”表示这个月的最一个星期五
	注意:在使用“L”参数时,不要指定列表或范围,因为这会导致问题
#	表示该月第n个星期x(x#n),仅用 DayofWeek 域,如:6#3 表示该月的第三个星期五
W	仅用在 DayofMonth 域中,表示距离当月给定日期最近的工作日(周一到周五),是单词"weekday"的缩写

注: 日と週を同時に指定することはできません。

例:

// 每天凌晨零点执行
@Scheduled(cron ="0 0 0 * * * ?")
// 每隔五分钟执行
@Scheduled(cron ="0 */5 * * * * ?")
// 在每天下午2点到下午2:55期间的每5分钟触发
@Scheduled(cron ="0 0/5 14 * * ?")
// 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
@Scheduled(cron ="0 0/5 14,18 * * ?")
// 在每天下午2点到下午2:05期间的每1分钟触发
@Scheduled(cron ="0 0-5 14 * * ?")
// 每个星期三中午12点
@Scheduled(cron ="0 0 12 ? * WED")
// 每月的第三个星期五上午10:15触发
@Scheduled(cron ="0 15 10 ? * 6#3")
// 每年三月的星期三的下午2:10和2:44触发
@Scheduled(cron ="0 10,44 14 ? 3 WED")
// 每月最后一日的上午10:15触发
@Scheduled(cron ="0 15 10 L * ?")
// 每月的最后一个星期五上午10:15触发
@Scheduled(cron ="0 15 10 ? * 6L")

Spring にはスケジューラが付属しています: @Scheduled

導入

実際、タイミング スケジューリングのためにアクセスできるサードパーティ プラットフォームは数多くありますが、実際、SpringBoot には独自のタイミング タスク アノテーション @Scheduled があります。@Scheduled は、@Scheduled アノテーションをメソッドに直接追加するだけで、アノテーション構成を通じてメソッドのタイミング スケジューリングを迅速に実現できます。

時限タスクの開始条件:

  • @Scheduled でマークされたメソッドのクラスが Spring コンテナ管理に渡されます (つまり、Spring IOC アノテーションがマークされます)。

  • @EnableScheduling アノテーションを構成クラス、または @Scheduled マーク付きメソッドが配置されているクラスに追加して、スケジュールされたタスク機能を有効にします。

    @EnableScheduling アノテーションの機能は、@Scheduled アノテーションが付けられたタスクを検出し、バックグラウンドで実行することです。


@Scheduled アノテーションパラメータ:

  • cronパラメータ: データ型は文字列です

    最も頻繁に使用されるパラメーター。時間式 (7 つの部分式) を受け取り、最大 7 つの時間要素を受け取ることを意味します。

  • ゾーンパラメータ

    取得するタイム ゾーンを指定します。デフォルトは空です。これは、サーバーが配置されているタイム ゾーン (Asia/BeiJingi や Asia/Shanghai など) を意味します。

  • 固定遅延パラメータ

    最後の実行の終了から次の実行までの固定時間をミリ秒単位で指定します。

    例: @Scheduled(fixedDelay= 3000) は、最後の呼び出しから 3 秒後に実行されることを示します

  • 固定遅延文字列パラメータ

    fixDelayString は fixDelay とほぼ同じですが、唯一の違いは、fixedDelayString がプレースホルダーをサポートしていることです。

  • 固定レートパラメータ

    実行する頻度をミリ秒単位で指定します。cron パラメータの / ワイルドカード効果と同様

    例: @Scheduled(fixedRate= 3000) は 3 秒ごとに実行することを意味します

  • 固定レート文字列パラメータ

    FixedRate パラメータのアップグレード、プレースホルダのサポート

  • 初期遅延パラメータ

    初めて実行が遅延する時間をミリ秒単位で示します。

    例: @Scheduled(initialDelay= 3000) は、初回実行時に実行が 3 秒遅れることを示します

  • 初期遅延文字列パラメータ

    InitialDelay パラメータのアップグレードでプレースホルダがサポートされる


知らせ

マイクロサービスが複数のインスタンスでデプロイされている場合、各マイクロサービス インスタンスはスケジュールされたスケジューリング タスクを同時に実行するため、大量の重複データが生成されたり、システム内で他のビジネス ロジックのバグが発生したりする可能性があります。そのため、タスクのスケジューリングに @Scheduled を使用する場合は、バグを避けるためにスケジュールされたスケジューリング タスクが 1 つのマイクロサービス インスタンスでのみ実行されるように、Redis の分散ロックとともに使用する必要があります。


使用例

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
 
import java.time.LocalDateTime;
 
@Component
@Slf4j
public class Task {
    
    
    
    // 每5秒执行一次
    @Scheduled(cron = "0/5 * * * * ?")
    public void task2(){
    
    
        log.warn("现在时间:" + LocalDateTime.now());
    }
    
    // 上⼀次开始执⾏时间点之后2秒再执⾏
    @Scheduled(fixedRate = 2000)
    public void task(){
    
    
        log.warn("现在时间:" + LocalDateTime.now());
    }
}

JDKネイティブタイマー

導入

タイマー。特定の時間に何かを実行するか、特定の時間に開始して、指定した間隔で繰り返し何かを実行するようにスレッドを設定できます。

java.util.Timerクラス: タイマーを記述するクラスです

スレッドがバックグラウンド スレッドで後で実行するタスクをスケジュールするために使用する機能。タスクは 1 回実行するか、定期的に繰り返すようにスケジュールできます。

施工方法:

public Timer()		// 创建一个新计时器。

メンバーメソッド:

// 终止此计时器,丢弃所有当前已安排的任务
void cancel()
    // 注意,在此计时器调用的计时器任务的 run 方法内调用此方法,就可以绝对确保正在执行的任务是此计时器所执行的最后一个任务。
    
// 在指定的毫秒值之后,执行指定的任务,只会执行一次
void schedule(TimerTask task, long delay) 	
// 在指定的毫秒值之后,执行指定的任务,之后每隔固定的毫秒数重复执行定时任务
void schedule(TimerTask task, long delay, long period)
// 安排在指定的时间执行指定的任务,只会执行一次
void schedule(TimerTask task, Date time) 
// 安排指定的任务在指定的时间开始进行重复的固定延迟执行
void schedule(TimerTask task, Date firstTime, long period) 
/* 参数:
		task		所要安排的任务。定时器到时间之后要执行的任务
		delay		执行任务前的延迟时间,单位是毫秒。 多个毫秒之后开始执行TimerTask任务
		period		执行各后续任务之间的时间间隔,单位是毫秒。定时器开始执行之后,每隔多少毫秒重复执行
		time		执行任务的时间。从什么日期开始执行任务  20020-07-06 15:25:13
		period		执行各后续任务之间的时间间隔,单位是毫秒。定时器开始执行之后,每隔多少毫秒重复执行
*/

TimerTask クラス: タイマーによって実行される 1 回限りのタスクまたは繰り返しのタスク

java.util.TimerTask はRunnableインターフェースを実装します

TimerTask クラスは抽象クラスであるため、直接作成できません

メンバー抽象メソッド:

// 此计时器任务要执行的操作。重写run方法,设置线程任务
void run()

使用例

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Demo01Timer {
    
    
    public static void main(String[] args) throws ParseException {
    
    
        show04();
    }
    
    /*
        在指定的毫秒值之后,执行指定的任务,只会执行一次
        void schedule(TimerTask task, long delay) 
    */
    private static void show01() {
    
    
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("c4爆炸了!");
                timer.cancel();
            }
        }, 5000);
    }
    
    /*
        在指定的毫秒值之后,执行指定的任务,之后每隔固定的毫秒数重复执行定时任务
        void schedule(TimerTask task, long delay, long period)
     */
    private static void show02() {
    
    
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Timer timer =new Timer();
        timer.schedule(new TimerTask() {
    
    
            @Override
            public void run() {
    
    
                System.out.println(sdf.format(new Date()));
            }
        }, 5000, 1000);
    }
    
    /*
        安排在指定的时间执行指定的任务,只会执行一次
        void schedule(TimerTask task, Date time) 
     */
    private static void show03() throws ParseException {
    
    
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = sdf.parse("2020-07-06 15:32:50");
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("哈哈!");
                timer.cancel();
            }
        }, date);
    }

    /*
        安排指定的任务在指定的时间开始进行重复的固定延迟执行
        void schedule(TimerTask task, Date firstTime, long period) 
     */
    private static void show04() throws ParseException {
    
    
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = sdf.parse("2020-07-06 15:37:30");
        Timer timer  = new Timer();
        timer.schedule(new TimerTask() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("嘿嘿,你中招了!");
            }
        }, date, 10);
    }
}

おすすめ

転載: blog.csdn.net/footless_bird/article/details/126679351