JAVA实现定时任务 从指定时间开始每隔 n 天执行一次, 可删除重设

本文描述的使用 Java 自带的 ScheduledExecutorService 来实现这个业务,直接看代码

涉及到的参数说明:

  1. ScheduledTaskManager 类负责管理定时任务的创建、取消和重设。
  2. scheduleTask 方法用于创建定时任务。它接受任务名称、开始时间、执行间隔和任务本身作为参数。
  3. cancelTask 方法用于取消定时任务。
  4. rescheduleTask 方法用于重设定时任务,它先取消原有任务,然后使用新的参数创建新的任务。
  5. getInitialDelay 方法计算从当前时间到开始时间的延迟时间(秒)。
import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

@Slf4j
public class CustomScheduledTaskManager {

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    private final Map<String, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();

    /**
     * 执行定时任务
     * @param taskName
     * @param startTime
     * @param intervalDays
     * @param task
     */
    public void scheduleTask(String taskName, LocalDateTime startTime, int intervalDays, Runnable task){
        log.info("CustomScheduledTaskManager task '{}' to run at {} every {} days========>", taskName, DateUtil.format(startTime, "yyyy-MM-dd HH:mm:ss"), intervalDays);
        long initialDelay = getInitialDelay(startTime, intervalDays);
        ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(task, initialDelay, intervalDays * 24 * 60 * 60, TimeUnit.SECONDS);
        scheduledTasks.put(taskName, future);
    }

    /**
     * 取消任务
     * @param taskName
     */
    public void cancelTask(String taskName) {
        log.info("CustomScheduledTaskManager task '{}' to cannel========>");
        ScheduledFuture<?> task = scheduledTasks.get(taskName);
        if (task != null) {
            task.cancel(true);
            scheduledTasks.remove(taskName);
        }
    }

    /**
     * 重新调度任务
     * @param taskName
     * @param newStartTime
     * @param newIntervalDays
     * @param task
     */
    public void rescheduleTask(String taskName, LocalDateTime newStartTime, int newIntervalDays, Runnable task) {
        cancelTask(taskName);
        scheduleTask(taskName, newStartTime, newIntervalDays, task);
    }

    /**
     * 计算延迟时间
     * @param startTime 任务执行时间
     * @return
     */
    private long getInitialDelay(LocalDateTime startTime) {
        LocalDateTime now = LocalDateTime.now();
        long seconds = startTime.toEpochSecond(java.time.ZoneOffset.UTC) - now.toEpochSecond(java.time.ZoneOffset.UTC);
        return seconds > 0 ? seconds : 0;
    }

    /**
     * 计算延迟时间
     * @param startTime 任务执行时间
     * @param intervalDays  延迟N天
     * @return
     */
    public static long getInitialDelay(LocalDateTime startTime, int intervalDays) {
        LocalDateTime endDateTime = LocalDateTime.now();
        long totalSeconds = Duration.between(startTime, endDateTime).getSeconds();
        if(totalSeconds < 0){
            return Math.abs(totalSeconds);
        }
        //long totalDays = totalSeconds / (24 * 60 * 60);
        //long fullNDayPeriods = totalDays / intervalDays;
        long remainingSeconds = totalSeconds % (intervalDays * 24 * 60 * 60);
        long additionalSeconds = intervalDays * 24 * 60 * 60 - remainingSeconds;
        return additionalSeconds;
    }
}

首先交给Bean管理,然后在需要的地方注入即可

    @Bean
    public CustomScheduledTaskManager customScheduledTaskManager() {
        return new CustomScheduledTaskManager();
    }


    @Resource
    private CustomScheduledTaskManager customScheduledTaskManager;
    @PostConstruct
    private void init() {
           log.info("定时任务初始化========>");                                               
           customScheduledTaskManager.scheduleTask(confConfig.getFieldKey(), confConfig.getGmtModified().toInstant()
                   .atZone(ZoneId.systemDefault())
                   .toLocalDateTime(), Integer.valueOf(confConfig.getFieldValue()), () -> {
               log.info("定时任务执行========>start------>");
               this.noticeManageService.timingPush();
               log.info("定时任务执行========>end------>");
           });
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值