schedule

发布时间 2023-05-06 19:40:18作者: rbcd
1、方式一

使用redission的特性来控制集群部署时的多次调用
缺点:单机的程序会在此处等待,导致其他任务没办法执行,原因是@Scheduled默认是单线程调度的

// 启动延时30秒执行,之后每隔60秒执行一次
@Scheduled(initialDelay = 30 * 1000, fixedDelay = 60 * 1000)
public void scheduledSync() {
    RLock lock = redissonClient.getLock(KEY);
    if (lock.tryLock()) {
        try {
        } catch (Exception e) {
        } finally {
            lock.unlock();
        }
    }
}
1.1、方式一可配置@Scheduled的多线程调用模式
@Bean
public TaskScheduler taskScheduler() {
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.setPoolSize(10);
    return taskScheduler;
}
2、方式二

使用线程池的特性来解决本次任务已执行完成,不耽误程序调度其他任务的执行;由于@Scheduled默认是单线程调度的,长时间占用此任务的话,其他任务都没法调用

// 自定义线程池,参数含义:
// 一个核心线程;
// 最大是一个线程;
// 线程回收空闲时间间隔零秒;
// 使用阻塞队列,队列最大存放任务量为一个;
// 在线程数已满、队列已满的情况下采取丢弃队列中旧的任务
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, new LinkedBlockingQueue(1), new ThreadPoolExecutor.DiscardOldestPolicy());

// 启动延时30秒执行,之后每隔60秒执行一次
@Scheduled(initialDelay = 30 * 1000, fixedDelay = 60 * 1000)
public void scheduledMethod() {
    executor.submit(() -> {
        try {
            int pageNo = 1;
            int pageSize = 50;
            List<Object> list;
            do {
                PageHelper.startPage(pageNo++, pageSize, false);
                list = selectData();
                list.foreach(obj->execMechod(obj));
            } while (!list.isEmpty() && list.size() >= pageSize);
        } catch (Exception e) {
            log.error("", e);
        }
    });
}
3、调度执行的方法
public void execMechod(Object obj) {
    RLock lock = redissonClient.getLock(KEY + obj.getId());
    if (lock.tryLock()) {
        try {
            // 是否需要再次验证数据状态
            int count = updateStatusData();
            if (count == 1) {
                // TODO 执行后续代码
            }
        } catch (Exception e) {
            log.error("", e);
        } finally {
            lock.unlock();
        }
    }
}