网站首页 全球最实用的IT互联网站!

人工智能P2P分享Wind搜索发布信息网站地图标签大全

当前位置:诺佳网 > 电子/半导体 > 嵌入式技术 >

SpringBoot如何实现定时任务(下)

时间:2023-04-07 14:51

人气:

作者:admin

标签:

导读:SpringBoot创建定时任务的方式很简单,主要有两种方式:一、基于注解的方式(@Scheduled)二、数据库动态配置。实际开发中,第一种需要在代码中写死表达式,如果修改起来,又得重启会...

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已经不再执行了

图片

最后

第二种方式支持通过接口的方式去改动,并且不需要重启,当然啦,也可以直接在数据库中添加或修改数据后重启项目,配置更加灵活一点。

如果是一个固定的需求,执行周期一定不会变的了,推荐还是第一种写法,毕竟简单嘛。

如果觉得写得还不错的话,给个推荐鼓励一下吧。

温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信