ScheduledExecutorService在spring中实现动态启停、修改间隔时间的功能(二) 动态配置起始时间

在第一部分我们已经实现了动态启停,修改间隔时间的功能,那么如果我们想要让某个定时任务只在每天的8点到12点执行,怎么办呢。对此我们可以对上一个项目https://blog.csdn.net/money9sun/article/details/88575704 进行升级

首先我们要对 ScheduledTask 增加两个字段 起始时间 我们设置成字符串格式 强制要求为12:00 这种格式

/** 开始时间 12:00*/
private String beginTime;
/** 结束时间 14:00*/
private String endTime;

然后对 ScheduledServiceImpl 增加几个map来保存不同状态下的任务

private Map<String, ScheduledTask> waitForStart = new ConcurrentHashMap<>(); // 等待开始

private Map<String, ScheduledTask> waitForEnd = new ConcurrentHashMap<>(); // 等待结束

private Map<String, ScheduledTask> completeSet = new ConcurrentHashMap<>(); // 已经完成

然后我们自定义三个线程

第一个触发开始线程 这个的作用是检查每个任务的开始时间,如果已经到了,就创建一个定时任务

private class StartTask implements Runnable {

    @Override
    public void run() {
        System.out.println("StartTask");
        // 循环遍历
        if (waitForStart.size() > 0) {

            Set<Map.Entry<String, ScheduledTask>> entries = waitForStart.entrySet();
            Iterator<Map.Entry<String, ScheduledTask>> iterator = entries.iterator();
            while (iterator.hasNext()) {
                // 取第一条数据
                ScheduledTask frist = iterator.next().getValue();
                String format = DateUtil.format(new Date(), "yyyy-MM-dd");
                Date endDate = DateUtil.gMT8StringToLocalDate(format + " " + frist.getEndTime(), "yyyy-MM-dd HH:mm");
                Date startDate = DateUtil.gMT8StringToLocalDate(format + " " + frist.getBeginTime(), "yyyy-MM-dd HH:mm");

                if (startDate.compareTo(new Date()) < 0 && endDate.compareTo(new Date()) > 0) {
                    // 开始方法
                    ScheduledFuture<?> scheduledFuture = service.scheduleWithFixedDelay(frist.getRunnable(), frist.getInitialDelay(), frist.getDelay(), TimeUnit.MILLISECONDS);

                    futureMap.put(frist.getTaskId(), scheduledFuture);
                    // 放入待关闭set中
                    System.out.println("StartTask 放入待关闭map");
                    waitForEnd.put(frist.getTaskId(), frist);
                    iterator.remove();
                }
                // 如果结束时间已经小于当前时间 表示本日不需要再执行 放入完成队列中
                if (endDate.compareTo(new Date()) < 0) {
                    iterator.remove();
                    System.out.println("StartTask 放入待重置map");
                    completeSet.put(frist.getTaskId(), frist);
                }
            }
        } else {
            // System.out.println("StartTask" + waitForStart.size());
        }
    }
}

第二个是检查结束线程 作用是检查任务是否已经到了结束时间 如果到了,就放入已结束队列

private class EndTask implements Runnable {

    @Override
    public void run() {
        // 取出TreeSet的第一条
        if (waitForEnd.size() > 0) {
            Set<Map.Entry<String, ScheduledTask>> entries = waitForEnd.entrySet();
            Iterator<Map.Entry<String, ScheduledTask>> iterator = entries.iterator();

            while (iterator.hasNext()) {
                // 取第一条数据
                ScheduledTask frist = iterator.next().getValue();
                String format = DateUtil.format(new Date(), "yyyy-MM-dd");
                Date date = DateUtil.gMT8StringToLocalDate(format + " " + frist.getEndTime(), "yyyy-MM-dd HH:mm");
                if (date.compareTo(new Date()) < 0) {
                    // 停止这个方法
                    remove(frist.getTaskId());
                    // 放入完成set中
                    iterator.remove();
                    System.out.println("EndTask 放入待重置map");
                    completeSet.put(frist.getTaskId(), frist);
                }
            }
        }
    }
}

第三个是重置线程,每天的夜里24点启动,目的是将已经结束的线程重新放入到待启动map中

 /**
     * 每天夜里24点执行 将已完成队列放入准备开始队列中
     *
     * @author Eric
     * @date 15:31 2019/3/13
     * @params null
     * @throws
     * @return
     **/
    private class initDaliy implements Runnable {

        @Override
        public void run() {
            waitForStart.putAll(completeSet);
        }
    }

最后在初始化方法内 添加这三个线程

@Override
public void afterPropertiesSet() throws Exception {
...
// 启动检测关闭线程
service.scheduleWithFixedDelay(new EndTask()
        , 1000, 5000, TimeUnit.MILLISECONDS);
// 启动检测开始线程
service.scheduleWithFixedDelay(new StartTask(), 1000, 5000, TimeUnit.MILLISECONDS);

LocalDateTime midnight = LocalDateTime.now().plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
long millSeconds = ChronoUnit.MILLIS.between(LocalDateTime.now(), midnight);
System.out.println("当天还剩的毫秒数" + millSeconds);
service.scheduleWithFixedDelay(new initDaliy(), millSeconds, 24*60*60*1000, TimeUnit.MILLISECONDS);

}

这样我们添加两个测试线程

addTask(new ScheduledTask("3", "scheduledTestService", "test1"
                , 5000, 1000
                , "14:15", "14:35"));

addTask(new ScheduledTask("4", "scheduledTestService", "test2"
                , 5000, 3000
                , "14:34", "14:40"));

执行的结果如下:

hello ScheduledTest

hello ScheduledTest

hello ScheduledTest

hello ScheduledTest

......

hello ScheduledTest

hello ScheduledTest

hello ScheduledTest

hello ScheduledTest2

hello ScheduledTest

EndTask 放入待重置map

StartTask

hello ScheduledTest2

StartTask

hello ScheduledTest2

hello ScheduledTest2

StartTask

好了,自定义起始时间已经完成了,下一步将继续优化,实现类似cron(0 0 2 * *)这样的功能

ScheduledExecutorService在spring中实现动态启停、修改间隔时间的功能(三)手动实现cron_专业的程序员的博客-CSDN博客

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值