Java開発の過程で、時限タスクの使用に遭遇することがよくあります。Timer、ScheduledExecutorService、SpringTask、Quartzの4つのメソッドを要約しました。
1つは、javaタイマーを使用する
1、タイマー
new Timer("testTimer").schedule(new TimerTask() {
@Override
public void run() {
System.out.println("TimerTask");
}
}, 1000,2000);
説明:1000msは遅延開始時間、2000msは時間指定されたタスクサイクルであり、2秒ごとに実行されます
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
try {
Date date = dateFormat.parse("2018-07-11 12:00:00.000");
new Timer("testTimer1").scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("TimerTask");
}
}, date,2000);
} catch (ParseException e) {
e.printStackTrace();
}
説明:日付は開始時刻、2000msは時間指定されたタスクサイクルです。
タイマーには、2秒ごとに実行される2つのメソッドscheduleとscheduleAtFixedRateがあります。前者はタスクの終了を待って時間間隔の計算を開始し、後者はタスクの開始時に時間を計算します。ハプニング
2つ目は、ScheduledExecutorServiceを使用する
1、ScheduledExecutorService
scheduledExecutorService.schedule(new Runnable() {
@Override
public void run() {
System.out.println("ScheduledTask");
}
},1, TimeUnit.SECONDS);
説明:開始を1秒遅らせ、1回実行します
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("ScheduledTask");
}
}, 1, 1, TimeUnit.SECONDS);
説明:1秒ごとに開始して実行するのを遅らせます。前のタスクが開始する時間間隔の計算を開始しますが、前のタスクの終了が次のタスクを開始するのを待ちます
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.out.println("ScheduledTask");
}
}, 1, 1, TimeUnit.SECONDS);
説明:開始するのに1秒遅れ、前のタスクが完了した後、実行するのに1秒遅れます
3、SpringTaskを使用します
1.タスクの作成
package com.zb.timedtask;
import com.zb.controller.StudentController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@Service
public class SpringTask {
private static final Logger log = LoggerFactory.getLogger(SpringTask.class);
@Scheduled(cron = "1/5 * * * * *")
public void task1(){
log.info("springtask 定时任务!");
}
@Scheduled(initialDelay = 1000,fixedRate = 1*1000)
public void task2(){
log.info("springtask 定时任务!");
}
}
説明:
task1は5秒ごとに実行され、{seconds} {minutes} {hour} {date} {month} {week}
task2は1秒遅れ、1秒ごとに実行されます
2.構成ファイルの変更
(1)シンプルバージョン
<task:annotation-driven/>
(2)タスクプールエディション
<task:executor id="executor" pool-size="10" />
<task:scheduler id="scheduler" pool-size="10" />
<task:annotation-driven executor="executor" scheduler="scheduler" />
(3)説明
時限タスクが1つしかない場合は、単純バージョンを使用できます。複数の時限タスクがある場合は、タスクプールを使用します。それ以外の場合は、順次実行されます。
2つのタスク間の時間間隔は次のとおりです。実行時間+設定されたタイミング間隔
例:(このタスクは8秒に1回実行されます)
@Scheduled(cron = "1/4 * * * * *")
public void task2(){
log.info("springtask 定时任务2!");
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
第四に、Quartzフレームワークを使用します
1.依存関係を追加します
<!-- quartz -->
<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>
<version>4.3.4.RELEASE</version>
</dependency>
2.ジョブの実装
package com.zb.quartz;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class HelloWorldJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
String strTime = new SimpleDateFormat("HH-mm-ss").format(new Date());
System.out.println( strTime + ":Hello World!");
}
}
3.スケジューラー(プロジェクトの開始時にリスナーを使用して実行できます)
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
public class MyScheduler {
public static void main(String[] args) throws SchedulerException {
//创建调度器Schedule
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
//创建JobDetail实例,并与HelloWordlJob类绑定
JobDetail jobDetail = JobBuilder.newJob(HelloWorldJob.class).withIdentity("job1", "jobGroup1")
.build();
//创建触发器Trigger实例(立即执行,每隔1S执行一次)
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "triggerGroup1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
.build();
//开始执行
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
}
}
注:HelloWorldJobが追加されていない場合
@PersistJobDataAfterExecution @DisallowConcurrentExecution
これらの2つの注釈を使用すると、ジョブはデフォルトで共有されます
つまり、スケジュールされたタスクの時間間隔は3秒であるが、ジョブの実行時間は10秒であると想定します。を設定する @DisallowConcurrentExecution
と、プログラムはタスクが実行されるのを待ってから実行します。そうでない場合、プログラムは3秒後に実行する新しいスレッドを開始します。
を設定するとき @PersistJobDataAfterExecution
は、ジョブexecution
メソッドの実行 後に固定データとリソースを保存して、タスクが繰り返し実行されたときに同じ操作リソースを持つようにします。デフォルトでは@PersistJobDataAfterExecution
、つまり、設定がない 場合、各ジョブには独立した操作リソースがあります。つまり、変数の値は独立しています。
したがって、これら2つの注釈を追加することをお勧めします
説明:上記は単純なトリガーです。次のように、Conトリガーを使用することもできます
Trigger cronTrigger = TriggerBuilder.newTrigger()
.withIdentity("trigger2", "triggerGroup2")
.startNow()
.withSchedule(cronSchedule("0 42 10 * * ?"))
.build();
4.スプリングを統合する
上記のスケジューラーを構成ファイルに直接書き込んで、Springを統合することもできます。
(1)仕事
package com.zb.quartz;
import java.text.SimpleDateFormat;
import java.util.Date;
public class QuarFirstJob {
public void first() {
String strTime = new SimpleDateFormat("HH-mm-ss").format(new Date());
System.out.println( strTime + ":Hello World!");
}
}
(2)構成ファイル
<bean id="QuarFirstJob" class="com.zb.quartz.QuarFirstJob" />
<bean id="jobDetail"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="group" value="quartzGroup1" />
<property name="name" value="quartzJob1" />
<!--false表示等上一个任务执行完后再开启新的任务 -->
<property name="concurrent" value="false" />
<property name="targetObject">
<ref bean="QuarFirstJob" />
</property>
<property name="targetMethod">
<value>first</value>
</property>
</bean>
<!-- 调度触发器 -->
<bean id="myTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="name" value="trigger1" />
<property name="group" value="group1" />
<property name="jobDetail">
<ref bean="jobDetail" />
</property>
<property name="cronExpression">
<value>0/5 * * * * ?</value>
</property>
</bean>
<!-- 调度工厂 -->
<bean id="scheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="myTrigger" />
</list>
</property>
</bean>
5.時間
public class QuarFirstJob {
public void first() {
try {
TimeUnit.SECONDS.sleep(6);
} catch (InterruptedException e) {
e.printStackTrace();
}
String strTime = new SimpleDateFormat("HH-mm-ss").format(new Date());
System.out.println( strTime + ":Hello World!");
}
}
上記の設定は5秒間隔として記述され、上記のスリープ時間はそれぞれ4と6に変更されます。2つのタスク間隔は実行時間と間隔時間の最大値であり、それぞれ5と6であることがわかります。
総括する
Quartzは、実行時間と間隔時間の最大値です(たとえば、実行時間が3秒の場合、間隔は2秒の場合、3秒ごとに実行されます。実行時間が3秒の場合、間隔は5秒、その後、5秒ごとに実行されます)
。Springタスクは実行時間+です。インターバル時間(たとえば、実行時間が3秒の場合、間隔は2秒、その後5秒ごとに実行されます。実行時間が3秒の場合、間隔は5秒、その後8秒ごとに実行されます。)
タイマーには2つのメソッドscheduleとscheduleAtFixedRateがあり、前者はタスクの終了を待機します。時間間隔の計算の開始時に、後者はタスクの開始時に時間を計算することであり、同時実行性があります
。ScheduledExecutorServiceのScheduleAtFixedRateはQuartzに似ており、scheduleWithFixedDelayはSpringTaskに似ています。