springboot+shedule之温故而知新

定时任务的实现方式

  • Timer:Java自带的java.util.Time类,这个类允许你调度一个java.util.TimerTask任务。这种方式让程序按照某个频度执行,但不能在指定时间执行。一般使用较少。
  • SheduledExecutorService:jdk自带的类,是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。
  • Spring Task:Spring3.0以后自带的task,相当于一个轻量级的Quartz。
  • Quartz:调度器可以让程序在指定的时间执行,也可以按照某个频度执行,配置起来稍显复杂。
    本文只分析后两个。
    一、Spring Task
    在SpringBoot项目中,我们可以很优雅的使用注解来实现定时任务,首先创建项目,添加starter-web依赖(默认包含了定时任务依赖),创建定时任务类,在启动类上使用@EnableScheduling注解开启对定时任务的支持即可。
    代码示例:
@Component
public class SheduleService {
    // 每5秒
    @Scheduled(cron = "0/5 * * * * *")
    public void scheduled() {
        System.out.println("=====>>>>>使用cron  " + System.currentTimeMillis());
    }

    @Scheduled(fixedRate = 5000)
    public void scheduled1() {
        System.out.println("=====>>>>>使用fixedRate  " + System.currentTimeMillis());
    }

    @Scheduled(fixedDelay = 5000)
    public void scheduled2() {
        System.out.println("=====>>>>>fixedDelay  " + System.currentTimeMillis());
    }
}
@SpringBootApplication
@EnableScheduling
public class SpringbootSheduleApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootSheduleApplication.class, args);
    }

}

结果:
=====>>>>>使用cron 1600760665001
=====>>>>>使用fixedRate 1600760668808
=====>>>>>fixedDelay 1600760668808
多线程执行
在SpringBoot项目中一般使用config配置类的方式添加配置,所以新建一个AsyncConfig类
然后在定时任务的类或者方法上添加@Async 。最后重启项目,每一个任务都是在不同的线程中。
corn表达式在此不去介绍。
结果:
=====>>>>>使用fixedRate 1600761599395taskExecutor-1
=====>>>>>fixedDelay 1600761599395taskExecutor-2
=====>>>>>使用cron 1600761600001taskExecutor-3
=====>>>>>使用fixedRate 1600761604391taskExecutor-4
=====>>>>>fixedDelay 1600761604393taskExecutor-5
=====>>>>>使用cron 1600761605002taskExecutor-6
=====>>>>>使用fixedRate 1600761609391taskExecutor-7
=====>>>>>fixedDelay 1600761609394taskExecutor-8
=====>>>>>使用cron 1600761610000taskExecutor-9
=====>>>>>使用fixedRate 1600761614390taskExecutor-10
=====>>>>>fixedDelay 1600761614395taskExecutor-1
=====>>>>>使用cron 1600761615001taskExecutor-2
二、Quartz
如果SpringBoot版本是2.0.0以后的,添加依赖spring-boot-starter-quartz即可。创建任务类QuartzService,继承QuartzJobBean
代码示例:

public class QuartzService extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("quartz task" + new Date());
    }
}
@Configuration
public class QuartzConfig {
    @Bean
    public JobDetail quartzDetail() {
        return JobBuilder.newJob(QuartzService.class).withIdentity("quartzService").storeDurably().build();
    }

    @Bean
    public Trigger quartzTrigger() {
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(10)  //设置时间周期单位秒
                .repeatForever();
        return TriggerBuilder.newTrigger().forJob(quartzDetail())
                .withIdentity("quartzService")
                .withSchedule(scheduleBuilder)
                .build();
    }
}

启动服务即可
结果:
quartz taskTue Sep 22 16:16:26 CST 2020
quartz taskTue Sep 22 16:16:36 CST 2020
quartz taskTue Sep 22 16:16:46 CST 2020
更复杂的定时任务:系统启动时获取任务信息开启定时任务,访问修改定时任务时间重启定时任务
代码示例:

public class MyJob implements Job {
    private final static Logger log = LoggerFactory.getLogger(MyJob.class);
    //@Autowired
    //private MyService myService;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        log.info("任务开始执行了");
        try {
            executeTask();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        log.info("任务执行结束了");
    }

    private void executeTask() throws SchedulerException {
        //myService.bizFunction();
        System.out.println("quartz定时任务执行内容");
    }
}
@Configuration
public class QuartzJobListener implements ApplicationListener<ContextRefreshedEvent> {
    private final static Logger log = LoggerFactory.getLogger(QuartzJobListener.class);
    @Autowired
    private QuartzManager quartzManager;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        try {
            // 开启一个指定的定时任务;需要设计从数据库获取定时任务对象列表,循环列表开启每个定时任务
            quartzManager.startJob();
            log.info("任务已经启动......");
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
    /**
     * 初始注入scheduler
     */
    @Bean
    public Scheduler scheduler() throws SchedulerException{
        SchedulerFactory schedulerFactoryBean = new StdSchedulerFactory();
        return schedulerFactoryBean.getScheduler();
    }
}
@Configuration
public class QuartzManager {

    public static final String JOB1="job1";
    public static final String GROUP1="group1";
    /**默认每个星期凌晨一点执行*/
    //public static final String DEFAULT_CRON="0 0 1 ? * L";
    /**默认5秒执行一次*/
    public static final String DEFAULT_CRON="*/5 * * * * ?";

    /**
     * 任务调度
     */
    @Autowired
    private Scheduler scheduler;

    /**
     * 开始执行定时任务
     */
    public void startJob() throws SchedulerException {
        startJobTask(scheduler);
        scheduler.start();
    }

    /**
     * 开始执行所有的定时任务
     */
    public void startAllJob(List<String> list) throws SchedulerException, ClassNotFoundException {
        startAllJobTask(scheduler,list);
        scheduler.start();
    }

    /**
     * 启动定时任务
     * @param scheduler
     */
    private void startJobTask(Scheduler scheduler) throws SchedulerException {
        JobDetail jobDetail= JobBuilder.newJob(MyJob.class).withIdentity(JOB1,GROUP1).build();
        CronScheduleBuilder cronScheduleBuilder=CronScheduleBuilder.cronSchedule(DEFAULT_CRON);
        CronTrigger cronTrigger=TriggerBuilder.newTrigger().withIdentity(JOB1,GROUP1).withSchedule(cronScheduleBuilder).build();
        scheduler.scheduleJob(jobDetail,cronTrigger);

    }

    /**
     * 启动所有的定时任务
     * @param scheduler
     */
    private void startAllJobTask(Scheduler scheduler,List<String> list) throws SchedulerException, ClassNotFoundException {
        Class clazz = Class.forName(list.get(0));
        JobDetail jobDetail= JobBuilder.newJob(clazz).withIdentity(list.get(1),list.get(2)).build();
        CronScheduleBuilder cronScheduleBuilder=CronScheduleBuilder.cronSchedule(list.get(3));
        CronTrigger cronTrigger=TriggerBuilder.newTrigger().withIdentity(JOB1,GROUP1).withSchedule(cronScheduleBuilder).build();
        scheduler.scheduleJob(jobDetail,cronTrigger);

    }

    /**
     * 获取Job信息
     * @param name
     * @param group
     */
    public String getjobInfo(String name,String group) throws SchedulerException {
        TriggerKey triggerKey=new TriggerKey(name,group);
        CronTrigger cronTrigger= (CronTrigger) scheduler.getTrigger(triggerKey);
        return String.format("time:%s,state:%s",cronTrigger.getCronExpression(),
                scheduler.getTriggerState(triggerKey).name());
    }

    /**
     * 修改任务的执行时间
     * @param name
     * @param group
     * @param cron cron表达式
     * @return
     * @throws SchedulerException
     */
    public boolean modifyJob(String name,String group,String cron) throws SchedulerException{
        Date date=null;
        TriggerKey triggerKey=new TriggerKey(name, group);
        CronTrigger cronTrigger= (CronTrigger) scheduler.getTrigger(triggerKey);
        String oldTime=cronTrigger.getCronExpression();
        if (!oldTime.equalsIgnoreCase(cron)){
            CronScheduleBuilder cronScheduleBuilder=CronScheduleBuilder.cronSchedule(cron);
            CronTrigger trigger=TriggerBuilder.newTrigger().withIdentity(name,group)
                    .withSchedule(cronScheduleBuilder).build();
            date=scheduler.rescheduleJob(triggerKey,trigger);
        }
        return date != null;
    }

    /**
     * 暂停所有任务
     * @throws SchedulerException
     */
    public void pauseAllJob()throws SchedulerException{
        scheduler.pauseAll();
    }

    /**
     * 暂停某个任务
     * @param name
     * @param group
     * @throws SchedulerException
     */
    public void pauseJob(String name,String group)throws SchedulerException{
        JobKey jobKey=new JobKey(name,group);
        JobDetail jobDetail=scheduler.getJobDetail(jobKey);
        if (jobDetail==null)
            return;
        scheduler.pauseJob(jobKey);
    }

    /**
     * 恢复所有任务
     * @throws SchedulerException
     */
    public void resumeAllJob()throws SchedulerException{
        scheduler.resumeAll();
    }
    /**
     * 恢复某个任务
     */
    public void resumeJob(String name,String group)throws SchedulerException{
        JobKey jobKey=new JobKey(name,group);
        JobDetail jobDetail=scheduler.getJobDetail(jobKey);
        if (jobDetail==null)
            return;
        scheduler.resumeJob(jobKey);
    }

    /**
     * 删除某个任务
     * @param name
     * @param group
     * @throws SchedulerException
     */
    public void deleteJob(String name,String group)throws SchedulerException {
        JobKey jobKey=new JobKey(name, group);
        JobDetail jobDetail=scheduler.getJobDetail(jobKey);
        if (jobDetail==null)
            return;
        scheduler.deleteJob(jobKey);
    }

}
@RestController
public class CronController {
    @Autowired
    private QuartzManager quartzManager;
    @GetMapping("modify")
    public String modify() throws SchedulerException {
        /**10秒执行一次*/
        String cron="*/10 * * * * ?";
        quartzManager.pauseJob(QuartzManager.JOB1,QuartzManager.GROUP1);
        quartzManager.modifyJob(QuartzManager.JOB1,QuartzManager.GROUP1,cron);
        return "ok";
    }
}

结果:
2020-09-22 17:26:05.001 INFO 7748 — [eduler_Worker-2] com.ldc.springboot_shedule.quartz.MyJob : 任务执行结束了
2020-09-22 17:26:10.001 INFO 7748 — [eduler_Worker-3] com.ldc.springboot_shedule.quartz.MyJob : 任务开始执行了

变更为
2020-09-22 17:31:10.001 INFO 7748 — [duler_Worker-10] com.ldc.springboot_shedule.quartz.MyJob : 任务执行结束了
2020-09-22 17:31:20.001 INFO 7748 — [eduler_Worker-1] com.ldc.springboot_shedule.quartz.MyJob : 任务开始执行了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值