1、需求

配置中,固定周期,单位秒。需要任务每间隔这个秒数 执行进行统计。
2、分析
要实现这个需求,之前一直在用的多线程方案也行。详见
既然前面用quartz 根据cron表达式上一次和下一次的执行时间判断。
本次就用quartz来实现动态任务。
毫无疑问,quartz更专业,功能更强大。支持事务,支持任务持久化。事务这边不需要。持久化看产品需求了。
3、编码实现
3.1 QuartzSchedulerConfig
@Configuration
public class QuartzSchedulerConfig {
    @Bean
    public SchedulerFactoryBean schedulerFactory() {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setBeanName("rules-scheduler");
        factory.setOverwriteExistingJobs(true);
        factory.setAutoStartup(true);
        return factory;
    }
}
 
 
3.2 FixedCycleSchedule
动态实现新增和删除 - 与数据库记录匹配
public class FixedCycleSchedule {
    private static final String GROUP = "fixed";
    @Autowired
    SchedulerFactoryBean schedulerFactoryBean;
    @Scheduled(fixedRate = 60 * 1000)
    private void configureTasks() {
        log.info("fixed cycle schedule single round start");
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        Map<String,CustomData> map = DbService.getFixedCycle().stream().collect(Collectors.toMap(CustomData::getId, Function.identity()));
        try {
            List<String> existingList = new ArrayList<>(16);
            for (TriggerKey triggerKey : scheduler.getTriggerKeys(GroupMatcher.groupEquals(GROUP))) {
                String taskName = triggerKey.getName();
                if (!map.containsKey(taskName)) {
                    System.out.println("remove " + taskName);
                    scheduler.unscheduleJob(triggerKey);
                    scheduler.deleteJob(JobKey.jobKey(taskName, GROUP));
                    continue;
                }
                existingList.add(taskName);
            }
            List<CustomData> adds = new ArrayList<>(16);
            for (String s : map.keySet()) {
                if(!existingList.contains(s)) {
                    adds.add(map.get(s));
                }
            }
            if(!adds.isEmpty()) {
                newTasks(scheduler,adds);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        log.info("fixed cycle schedule single round end");
    }
    private void newTasks(Scheduler scheduler, List<CustomData> adds) throws Exception{
        for (CustomData customData : adds) {
            JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                    .withIdentity(customData.getId(), GROUP)
                    .build();
            SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                    .withIntervalInSeconds(customData.getCycle())
                    .repeatForever();
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(customData.getId(), GROUP)
                    .startNow()
                    .withSchedule(scheduleBuilder)
                    .build();
            System.out.println("newTasks " + customData.getId());
            scheduler.scheduleJob(jobDetail, trigger);
        }
    }
}
 
用spring的schedule每一分钟同步一次。
3.3 Job
public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        // 获取 Trigger
        Trigger trigger = context.getTrigger();
        TriggerKey key = trigger.getKey();
        // 获取 Scheduler
        Scheduler scheduler = context.getScheduler();
        System.out.println("context.getJobDetail().getKey().getName() = " + key.getName());
        System.out.println("Job executed at " + new Date());
        SimpleTrigger t = (SimpleTrigger)trigger;
        System.out.println("t.getRepeatInterval() = " + t.getRepeatInterval());
        try {
            if(queryDatabaseForNewSecond == 1) {
                scheduler.pauseTrigger(key);
                scheduler.unscheduleJob(key);
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
} 
queryDatabaseForNewSecond==1 可以用来与库中对比,周期配置如有变更,那么需要更新。一开始打算在job中直接更新,更新也是需要停掉,再newScheduleBuilder、newTrigger,再启 。那么直接停掉。外面的FixedCycleSchedule也会再新建
4、结语
Quartz 方式
优点
-  
高级调度能力:
- Quartz 提供了丰富的调度功能,如固定间隔、固定频率、基于日历的调度等。
 - 可以轻松配置复杂的调度策略,如在特定日期和时间执行任务。
 
 -  
任务管理:
- 支持任务的暂停、恢复、取消等功能。
 - 可以查看任务的状态,如是否正在执行、何时执行等。
 
 -  
持久化支持:
- Quartz 可以将调度信息持久化到数据库中,这样即使应用程序重启,调度也不会丢失。
 - 支持集群部署,可以在多个节点之间共享调度信息。
 
 -  
灵活性:
- 支持多种类型的触发器,如 
SimpleTrigger和CronTrigger。 - 可以配置多个触发器来调度同一个作业。
 
 - 支持多种类型的触发器,如 
 -  
健壮性:
- Quartz 在设计时考虑了高可用性和容错性。
 - 支持故障转移和恢复,可以在任务失败时自动重试。
 
 
多线程方式
优点
-  
简单易用:
- Java 提供了强大的多线程支持,如 
Thread和Runnable接口。 - 可以轻松创建线程并控制线程的生命周期。
 
 - Java 提供了强大的多线程支持,如 
 -  
轻量级:
- 相对于 Quartz,多线程模型更为轻量级。
 - 不需要额外的配置或持久化支持。
 
 -  
灵活的任务执行:
- 可以根据需要自由控制线程的启动和停止。
 - 可以使用 
ExecutorService来管理线程池,提高资源利用率。 
 
择优而用!



















