2.6 定時任務(wù)管理實現(xiàn)類
@Slf4j
@Service
public class ScheduledTaskServiceImpl implements ScheduledTaskService {
/**
* 可重入鎖
*/
private ReentrantLock lock = new ReentrantLock();
/**
* 定時任務(wù)線程池
*/
@Autowired
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
/**
* 啟動狀態(tài)的定時任務(wù)集合
*/
public Map<String, ScheduledFuture> scheduledFutureMap = new ConcurrentHashMap<>();
@Autowired
private ScheduledJobService scheduledJobService;
@Override
public Boolean start(ScheduledJob scheduledJob) {
String jobKey = scheduledJob.getJobKey();
log.info("啟動定時任務(wù)"+jobKey);
//添加鎖放一個線程啟動,防止多人啟動多次
lock.lock();
log.info("加鎖完成");
try {
if(this.isStart(jobKey)){
log.info("當(dāng)前任務(wù)在啟動狀態(tài)中");
return false;
}
//任務(wù)啟動
this.doStartTask(scheduledJob);
} finally {
lock.unlock();
log.info("解鎖完畢");
}
return true;
}
/**
* 任務(wù)是否已經(jīng)啟動
*/
private Boolean isStart(String taskKey) {
//校驗是否已經(jīng)啟動
if (scheduledFutureMap.containsKey(taskKey)) {
if (!scheduledFutureMap.get(taskKey).isCancelled()) {
return true;
}
}
return false;
}
@Override
public Boolean stop(String jobKey) {
log.info("停止任務(wù) "+jobKey);
boolean flag = scheduledFutureMap.containsKey(jobKey);
log.info("當(dāng)前實例是否存在 "+flag);
if(flag){
ScheduledFuture scheduledFuture = scheduledFutureMap.get(jobKey);
scheduledFuture.cancel(true);
scheduledFutureMap.remove(jobKey);
}
return flag;
}
@Override
public Boolean restart(ScheduledJob scheduledJob) {
log.info("重啟定時任務(wù)"+scheduledJob.getJobKey());
//停止
this.stop(scheduledJob.getJobKey());
return this.start(scheduledJob);
}
/**
* 執(zhí)行啟動任務(wù)
*/
public void doStartTask(ScheduledJob sj){
log.info(sj.getJobKey());
if(sj.getStatus().intValue() != 1)
return;
Class? clazz;
ScheduledOfTask task;
try {
clazz = Class.forName(sj.getJobKey());
task = (ScheduledOfTask) SpringContextUtil.getBean(clazz);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("spring_scheduled_cron表數(shù)據(jù)" + sj.getJobKey() + "有誤", e);
}
Assert.isAssignable(ScheduledOfTask.class, task.getClass(), "定時任務(wù)類必須實現(xiàn)ScheduledOfTask接口");
ScheduledFuture scheduledFuture = threadPoolTaskScheduler.schedule(task,(triggerContext -> new CronTrigger(sj.getCronExpression()).nextExecutionTime(triggerContext)));
scheduledFutureMap.put(sj.getJobKey(),scheduledFuture);
}
@Override
public void initTask() {
List
2.8 上面用到的獲取Bean的工具類SpringContextUtil
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringContextUtil.applicationContext == null){
SpringContextUtil.applicationContext = applicationContext;
}
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
public static
2.9 表操作對應(yīng)的一些類
Pojo
@Data
@TableName("scheduled_job")
public class ScheduledJob {
@TableId(value = "job_id",type = IdType.AUTO)
private Integer jobId;
private String jobKey;
private String cronExpression;
private String taskExplain;
private Integer status;
}
ScheduledJobMapper
public interface ScheduledJobMapper extends BaseMapper<ScheduledJob> {
}
ScheduledJobService
public interface ScheduledJobService extends IService<ScheduledJob> {
/**
* 修改定時任務(wù),并重新啟動
* @param scheduledJob
* @return
*/
boolean updateOne(ScheduledJob scheduledJob);
}
@Service
@Slf4j
public class ScheduledJobServiceImpl extends ServiceImpl
2.10 修改定時任務(wù)的接口
@RestController
@RequestMapping("/job")
public class ScheduledJobController {
@Autowired
private ScheduledJobService scheduledJobService;
@PostMapping(value = "/update")
public CallBackResult update(HttpServletRequest request, ScheduledJob scheduledJob){
if(scheduledJobService.updateOne(scheduledJob))
return new CallBackResult(true,"修改成功");
return new CallBackResult(false,"修改失敗");
}
}
3、測試結(jié)果
3.1 啟動項目,看下定時任務(wù)的執(zhí)行結(jié)果,控制臺輸出結(jié)果
我們可以看到任務(wù)1是每5秒執(zhí)行一次,任務(wù)2是12秒執(zhí)行一次
3.2 修改任務(wù)1的cron參數(shù)或者狀態(tài)
3.2.1 修改cron,執(zhí)行周期改為20秒執(zhí)行一次,狀態(tài)不變
再看控制臺輸出結(jié)果,任務(wù)2沒變化,任務(wù)1由5秒一次變成了20秒一次了
3.2.1 修改狀態(tài)
再看控制臺輸出結(jié)果,任務(wù)2沒變化,任務(wù)1已經(jīng)不再執(zhí)行了
最后
第二種方式支持通過接口的方式去改動,并且不需要重啟,當(dāng)然啦,也可以直接在數(shù)據(jù)庫中添加或修改數(shù)據(jù)后重啟項目,配置更加靈活一點。
如果是一個固定的需求,執(zhí)行周期一定不會變的了,推薦還是第一種寫法,畢竟簡單嘛。
如果覺得寫得還不錯的話,給個推薦鼓勵一下吧。
-
代碼
+關(guān)注
關(guān)注
30文章
4779瀏覽量
68525 -
spring
+關(guān)注
關(guān)注
0文章
340瀏覽量
14338 -
Boot
+關(guān)注
關(guān)注
0文章
149瀏覽量
35823 -
SpringBoot
+關(guān)注
關(guān)注
0文章
173瀏覽量
177
發(fā)布評論請先 登錄
相關(guān)推薦
評論