前言
最近項目中在使用企業級定時任務Quartz,在使用過程中,發現一個問題就是我們如何防止定時任務的併發?
定時任務的併發
- 正常執行
- 併發
通過上面的圖片,我們瞭解了併發任務,在實際的項目開發中,如何防止併發呢?
@DisallowConcurrentExecution 防止併發
模擬併發
package com.zcw;
import com.zcw.job.MyJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
/**
* @ClassName : QuartzDemo
* @Description :啓動類
* @Author : Zhaocunwei
* @Date: 2020-06-09 13:31
*/
public class QuartzDemo {
public static void main(String[] args) throws SchedulerException {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
//配置任務
JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
.withIdentity("jobDetail1","group1")
.usingJobData("name","zcw")
.build();
//創建觸發器
Trigger trigger = TriggerBuilder.newTrigger()
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
//時間間隔爲5秒
.withIntervalInSeconds(5)
.repeatForever()
).build();
scheduler.scheduleJob(jobDetail,trigger);
try {
Thread.sleep(600000);
} catch (InterruptedException e) {
e.printStackTrace();
}
scheduler.shutdown();
}
}
- job類
package com.zcw.job;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import java.time.LocalTime;
/**
* @ClassName : MyJob
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-06-09 13:32
*/
@Data
public class MyJob implements Job {
private String name;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
LocalTime localTime = LocalTime.now();
System.out.println(Thread.currentThread().getName()+"開始執行!"+localTime.toString());
try {
Thread.sleep(7000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LocalTime endTime = LocalTime.now();
System.out.println("結束時間!"+endTime.toString());
}
}
- 測試結果
優化代碼,解決併發添加註解
package com.zcw.job;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import java.time.LocalTime;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @ClassName : MyJob
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-06-09 13:32
*/
@Data
@DisallowConcurrentExecution
public class MyJob implements Job {
private String name;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
LocalTime localTime = LocalTime.now();
System.out.println(Thread.currentThread().getName()+"開始執行!"+localTime.toString());
try {
Thread.sleep(7000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LocalTime endTime = LocalTime.now();
System.out.println(Thread.currentThread().getName()+"結束時間!"+endTime.toString());
}
}
- 測試
JobDataMap的更新
在這裏主要是演示一個@PersistJobDataAfterExecution可更新JobDataMap註解,把數據持久化到我們的jobDataMap中。
- 測試
通過上面的演示,我們的count值沒有增加,需要每次執行一次count+1;
package com.zcw.job;
import lombok.Data;
import org.quartz.*;
import java.time.LocalTime;
/**
* @ClassName : MyJob
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-06-09 13:32
*/
@Data
@PersistJobDataAfterExecution
public class MyJob implements Job {
private int count;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
LocalTime localTime = LocalTime.now();
count++;
context.getJobDetail().getJobDataMap().put("count",count);
System.out.println(localTime.toString()+",count值="+count);
}
}
- 測試