电子说
2.6 定时任务管理实现类
@Slf4j
@Service
public class ScheduledTaskServiceImpl implements ScheduledTaskService {
/**
* 可重入锁
*/
private ReentrantLock lock = new ReentrantLock();
/**
* 定时任务线程池
*/
@Autowired
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
/**
* 启动状态的定时任务集合
*/
public Map<String, ScheduledFuture> scheduledFutureMap = new ConcurrentHashMap<>();
@Autowired
private ScheduledJobService scheduledJobService;
@Override
public Boolean start(ScheduledJob scheduledJob) {
String jobKey = scheduledJob.getJobKey();
log.info("启动定时任务"+jobKey);
//添加锁放一个线程启动,防止多人启动多次
lock.lock();
log.info("加锁完成");
try {
if(this.isStart(jobKey)){
log.info("当前任务在启动状态中");
return false;
}
//任务启动
this.doStartTask(scheduledJob);
} finally {
lock.unlock();
log.info("解锁完毕");
}
return true;
}
/**
* 任务是否已经启动
*/
private Boolean isStart(String taskKey) {
//校验是否已经启动
if (scheduledFutureMap.containsKey(taskKey)) {
if (!scheduledFutureMap.get(taskKey).isCancelled()) {
return true;
}
}
return false;
}
@Override
public Boolean stop(String jobKey) {
log.info("停止任务 "+jobKey);
boolean flag = scheduledFutureMap.containsKey(jobKey);
log.info("当前实例是否存在 "+flag);
if(flag){
ScheduledFuture scheduledFuture = scheduledFutureMap.get(jobKey);
scheduledFuture.cancel(true);
scheduledFutureMap.remove(jobKey);
}
return flag;
}
@Override
public Boolean restart(ScheduledJob scheduledJob) {
log.info("重启定时任务"+scheduledJob.getJobKey());
//停止
this.stop(scheduledJob.getJobKey());
return this.start(scheduledJob);
}
/**
* 执行启动任务
*/
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表数据" + sj.getJobKey() + "有误", e);
}
Assert.isAssignable(ScheduledOfTask.class, task.getClass(), "定时任务类必须实现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 表操作对应的一些类
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> {
/**
* 修改定时任务,并重新启动
* @param scheduledJob
* @return
*/
boolean updateOne(ScheduledJob scheduledJob);
}
@Service
@Slf4j
public class ScheduledJobServiceImpl extends ServiceImpl
2.10 修改定时任务的接口
@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、测试结果
3.1 启动项目,看下定时任务的执行结果,控制台输出结果
我们可以看到任务1是每5秒执行一次,任务2是12秒执行一次
3.2 修改任务1的cron参数或者状态
3.2.1 修改cron,执行周期改为20秒执行一次,状态不变
再看控制台输出结果,任务2没变化,任务1由5秒一次变成了20秒一次了
3.2.1 修改状态
再看控制台输出结果,任务2没变化,任务1已经不再执行了
第二种方式支持通过接口的方式去改动,并且不需要重启,当然啦,也可以直接在数据库中添加或修改数据后重启项目,配置更加灵活一点。
如果是一个固定的需求,执行周期一定不会变的了,推荐还是第一种写法,毕竟简单嘛。
如果觉得写得还不错的话,给个推荐鼓励一下吧。
全部0条评论
快来发表一下你的评论吧 !