Javaでタイミングを使用する方法

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に似ています。

おすすめ

転載: blog.csdn.net/ClearLoveQ/article/details/105753391