ホームページ  >  記事  >  Java  >  Spring Boot で複数のスケジュールされたタスクを実装する方法

Spring Boot で複数のスケジュールされたタスクを実装する方法

Java后端技术全栈
Java后端技术全栈転載
2023-08-15 16:50:341345ブラウズ

実際の開発では、多かれ少なかれいくつかのスケジュールされたタスクのシナリオが使用されます。この記事では、一般的に使用されるスケジュールされたタスクについて説明します。

一般的に使用されるタイミング タスクの実装ソリューションには次のものがあります。

  • Timer: これは、Java に付属する java.util.Timer クラスです。このクラスを使用すると、java.util.TimerTask タスクをスケジュールできます。 。この方法を使用すると、指定された時間ではなく、特定の頻度でプログラムを実行できます。一般的にはあまり使用されません。
  • ScheduledExecutorService: これも jdk に付属するクラスであり、スレッド プール設計に基づいたスケジュールされたタスク クラスです。各スケジュールされたタスクは、次のように割り当てられます。スレッド プール スレッドが実行されます。つまり、タスクは同時に実行され、互いに影響しません。
  • Spring タスク:Spring3.0今後のタスクでは、これを軽量の Quartz とみなして使用できます。Quartz よりもはるかに単純です。
  • Quartz: これは、指定した時間または周波数でプログラムを実行できるようにする比較的強力なスケジューラです。設定は少し複雑です。
  • データベースにテーブルを作成し、cron 式をテーブルに保存します。
  • nacos、分散構成を使用して動的構成 cron 式を実装します。
  • XXL-JOB、分散タスク

タイマーの使用

これは現在プロジェクトで使用されることはほとんどなく、デモ コードが直接投稿されます。

詳細な紹介については、API をご覧ください:

public class TestTimer {
    public static void main(String[] args) {
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("task  run:"+ new Date());
            }
        };
        Timer timer = new Timer();
        //安排指定的任务在指定的时间开始进行重复的固定延迟执行。这里是每3秒执行一次
        timer.schedule(timerTask,10,3000);
    }
}

Use ScheduledExecutorService

このメソッドはタイマーに似ています。デモを見てください:

public class TestScheduledExecutorService {
    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        // 参数:1、任务体 2、首次执行的延时时间
        //      3、任务执行间隔 4、间隔时间单位
        service.scheduleAtFixedRate(()->System.out.println("task ScheduledExecutorService "+new Date()), 0, 3, TimeUnit.SECONDS);
    }
}

Use Spring Task

単純なスケジュールされたタスク

Spring Boot プロジェクトでは、アノテーションを使用して、スケジュールされたタスクを非常にエレガントに実装できます。まず、プロジェクトを作成し、依存関係をインポートします。 :

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>

タスク クラスを作成します:

@Slf4j
@Component
public class ScheduledService {
    @Scheduled(cron = "0/5 * * * * *")
    public void scheduled(){
        log.info("=====>>>>>使用cron  {}",System.currentTimeMillis());
    }
    @Scheduled(fixedRate = 5000)
    public void scheduled1() {
        log.info("=====>>>>>使用fixedRate{}", System.currentTimeMillis());
    }
    @Scheduled(fixedDelay = 5000)
    public void scheduled2() {
        log.info("=====>>>>>fixedDelay{}",System.currentTimeMillis());
    }
}

メイン クラスで @EnableScheduling アノテーションを使用して、スケジュールされたタスクのサポートを有効にして、プロジェクトを開始します

Spring Boot で複数のスケジュールされたタスクを実装する方法

3 つのスケジュールされたタスクがすべて実行され、それらが同じスレッド内で連続して実行される場合、スケジュールされたタスクが 1 つだけであれば、これは間違いなく問題ありません。スケジュールされたタスクの数が増加すると、 1 つのタスクが停止すると、他のタスクは実行できなくなります。

マルチスレッド実行

従来の Spring プロジェクトでは、xml 構成ファイルにタスク構成を追加できますが、Spring Boot プロジェクトでは通常、構成を追加するために config 構成クラスを使用します。新しい AsyncConfig class

@Configuration
@EnableAsync
public class AsyncConfig {
     /*
    此处成员变量应该使用@Value从配置中读取
     */
    private int corePoolSize = 10;
    private int maxPoolSize = 200;
    private int queueCapacity = 10;
    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.initialize();
        return executor;
    }
}

@Configuration: このクラスが構成クラスであることを示します@EnableAsync: 非同期イベントのサポートを有効にします

次に、スケジュールされたタスクのクラスまたはメソッドに @Async を追加します。最後にプロジェクトを再起動します。各タスクは別のスレッドにあります。

Spring Boot で複数のスケジュールされたタスクを実装する方法

実行時間の構成

上記のスケジュールされたタスクでは、メソッドの @Scheduled アノテーションを使用してタスクの実行時間を設定します。 3 つのプロパティ設定方法を使用します:

  1. fixedRate: 特定の頻度で実行されるスケジュールされたタスクを定義します
  2. fixedDelay: 特定の頻度で実行されるスケジュールされたタスクを定義します。上記のことから、この属性を initialDelay と組み合わせて変更して、タスクの遅延実行時間を定義できることがわかります。
  3. cron: 式を使用してタスクの実行時間を構成する

cron 式の詳細な説明

cron 式には少なくとも 6 つの値が含まれます(おそらく 7 つ) スペースで区切られた時間要素。順序:

  • 秒 (0 ~ 59)
  • # 分 (0 ~ 59)
  • 3 時間 (0 ~ 23)
  • 4 日 (0 ~ 31)
  • 5 か月 (0 ~ 11)
  • 6 週 (1~7 1=日または日、月、火、水、木、金、土)
  • 年 (1970-2099)
#各要素には、値 (6 など)、連続間隔 (9 ~ 12)、間隔 (8 ~ 18/4) (/ はそれぞれ 4 時間間隔を意味します)、リスト (1,3,5)、ワイルドカード。 「日」と「曜日」の 2 つの要素は相互に排他的であるため、どちらか一方を設定する必要があります。構成例:

  • 5 秒ごとに実行: */5* * ?
  • 1 分ごとに実行: 0 /1 ?
  • 0 0 10,14,16 ? 毎日午前 10 時、午後 2 時、午後 4 時
  • 0 0/30 9-17 ? 30 分ごと9 時から 5 時までの勤務時間中
  • #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 分までは 5 分ごとにトリガーし、午後 6 時から午後 6 時 55 分までは 5 分ごとにトリガーします。
  • "0 0-5 14 ?" 午後 2 時から午後 2 時までは 1 分ごとにトリガーします毎日午後 5 時
  • 「0 10,44 14 ? 3 WED」 3 月の毎週水曜日午後 2 時: 10 時と 2 時 44 分にトリガー
  • "0 15 10 ? * MON-FRI" 月曜日から金曜日の午前 10 時 15 分にトリガーされます。
  • "0 15 10 15 * ?" 月曜日から金曜日の午前 10 時 15 分にトリガーされます。毎月 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" 毎月第 3 金曜日の午前 10 時 :15 トリガー
  • 一部の部分式には範囲またはリストを含めることができます
例: 部分式 (日 (週)) は、「MON-FRI」、「MON、WED、FRI」にすることができます。 、「MON-WED,SAT」

「*」文字はすべての可能な値を表します 「/」文字は値の増分を指定するために使用されます

例: 部分式 (分) の「0/15」は、0 分から 15 分ごとに開始することを意味します。 部分式(分)の「3/20」は、3分から20分ごと(「3、23、43」と同じ意味です)

"?"を意味します。文字は、日 (月) と日 (週) の 2 つの部分式でのみ使用され、値が指定されていないことを示します。 2 つの部分式のいずれかに値が割り当てられている場合、競合を避けるために、もう一方の部分式の値を「?」に設定する必要があります。

「L」文字は日 (月) にのみ使用されます。および day (week) は 2 つの部分式であり、単語「last」の省略形です。 「L」の前に何か特定のものがある場合、それは他の意味を持ちます。

例: 「6L」は今月の 6 日から末日までを意味します 注: 「L」パラメータを使用する場合は、問題が発生するため、リストまたは範囲を指定しないでください。

#W 文字は平日 (月曜から金曜) を表し、日中にのみ使用できます。ドメイン。指定した日付に最も近い平日を指定するために使用されます。ほとんどの業務処理は週の労働時間に基づいているため、W の文字は非常に重要です。

たとえば、日フィールドの 15W は、「月の 15 日に最も近い平日」を意味します。15 日が土曜日の場合、トリガーは 14 日 (金曜日) にトリガーされます。木曜日は月曜日よりも小さいので、15日に近いからです。

C: 「カレンダー」の略です。これは、スケジュールに関連付けられた日付、または日付が関連付けられていない場合はカレンダー内のすべての日付を意味します。

たとえば、日付フィールドの 5C は、カレンダーの 5 日後の最初の日に相当します。曜日フィールドの 1C は、日曜日の後の最初の日に対応します。

##秒0~59, - * /##分時間 日付1-31, - * ? / L W C1~12 または JAN~DEC1~7 または SUN~SAT空白のまま、1970~2099
フィールド 許可される値 許可される特殊文字
0~59 , - * /
#0~23 , - * /
##month
, - * / 平日
, - * ? / L C #年 (オプション)
、- * /

在线cron表达式生成:http://qqe2.com/cron/index

整合Quartz

  • 添加依赖

如果Spring Boot版本是2.0.0以后的,则在spring-boot-starter中已经包含了quart的依赖,则可以直接使用spring-boot-starter-quartz依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

如果是1.5.9则要使用以下添加依赖:

<dependency>
  <groupId>org.quartz-scheduler</groupId>
  <artifactId>quartz</artifactId>
  <version>2.3.0</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context-support</artifactId>
</dependency>

这里我使用Spring Boot版本是2.0.0.BUILD-SNAPSHOT ,该版本开始集成了Quartz,所以事实现起来很方便。其它好像比较麻烦,这里就不介绍,以后有时间再详细深入了解Quartz。

  • 创建任务类TestQuartz,该类主要是继承了QuartzJobBean
public class TestQuartz extends QuartzJobBean {
    /**
     * 执行定时任务
     * @param jobExecutionContext
     * @throws JobExecutionException
     */
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("quartz task "+new Date());
    }
}
  • 创建配置类QuartzConfig
@Configuration
public class QuartzConfig {
    @Bean
    public JobDetail teatQuartzDetail(){
        return JobBuilder.newJob(TestQuartz.class).withIdentity("testQuartz").storeDurably().build();
    }

    @Bean
    public Trigger testQuartzTrigger(){
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(10)  //设置时间周期单位秒
                .repeatForever();
        return TriggerBuilder.newTrigger().forJob(teatQuartzDetail())
                .withIdentity("testQuartz")
                .withSchedule(scheduleBuilder)
                .build();
    }
}
  • 启动项目

Spring Boot で複数のスケジュールされたタスクを実装する方法

最后

上面都是简单的介绍了关于Spring Boot定时任务的处理,直接使用SpringTask注解的方式应该是最方便的,而使用Quartz从2.0开始也变得很方便。对于这两种方式,应该说各有长处吧,按需选择。

以上がSpring Boot で複数のスケジュールされたタスクを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はJava后端技术全栈で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。