SpringBoot实现指定时间开启定时任务

使用 @Scheduled注解可以快速的设置异步任务
但是只能指定固定的corn不能做到动态修改

业务场景:
当前端传来一个时间,我们需要在这个时间点的时候,执行对应的任务
这时@Scheduled注解就不能满足我们的需要了

我们通过TaskSchedulerScheduledFuture schedule(Runnable task, Trigger trigger);`方法来实现,
定时任务结束之后,就不会在执行

具体代码


/**
 * 异步线程池ThreadPoolExecutor 配置类
 *
 */
@Configuration
public class ThreadPoolTaskExecutorConfig {

    @Bean
    public ThreadPoolTaskScheduler syncScheduler() {
        ThreadPoolTaskScheduler syncScheduler = new ThreadPoolTaskScheduler();
        syncScheduler.setPoolSize(5);
        // 这里给线程设置名字,主要是为了在项目能够更快速的定位错误。
        syncScheduler.setThreadGroupName("syncTg");
        syncScheduler.setThreadNamePrefix("syncThread-");
        syncScheduler.initialize();
        return syncScheduler;
    }
}

import cn.hutool.core.convert.ConverterRegistry;
import com.crush.scheduled.entity.Task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledFuture;


@Component
@Slf4j
public class DynamicTaskService {

    /**
     * 以下两个都是线程安全的集合类。
     */
    public Map<String, ScheduledFuture<?>> taskMap = new ConcurrentHashMap<>();
    public List<String> taskList = new CopyOnWriteArrayList<String>();


    private final ThreadPoolTaskScheduler syncScheduler;

    public DynamicTaskService(ThreadPoolTaskScheduler syncScheduler) {
        this.syncScheduler = syncScheduler;
    }

    /**
     * 查看已开启但还未执行的动态任务
     * @return
     */
    public List<String> getTaskList() {
        return taskList;
    }


    /**
     * 添加一个动态任务
     *
     * @param task
     * @return
     */
    public boolean add(Task task) {
        // 此处的逻辑是 ,如果当前已经有这个名字的任务存在,先删除之前的,再添加现在的。(即重复就覆盖)
        if (null != taskMap.get(task.getName())) {
            stop(task.getName());
        }

//将localdate转换为date
        Date startTime= CommonUtil.formate(task.getStart());

        // schedule :调度给定的Runnable ,在指定的执行时间调用它。
        //一旦调度程序关闭或返回的ScheduledFuture被取消,执行将结束。
        //参数:
        //任务 – 触发器触发时执行的 Runnable
        //startTime – 任务所需的执行时间(如果这是过去,则任务将立即执行,即尽快执行)
        ScheduledFuture<?> schedule = syncScheduler.schedule(getRunnable(task), startTime);
        taskMap.put(task.getName(), schedule);
        taskList.add(task.getName());
        return true;
    }


    /**
     * 运行任务
     *
     * @param task
     * @return
     */
    public Runnable getRunnable(Task task) {
    
        return () -> {
            log.info("---动态定时任务运行---");
            try {
                System.out.println("此时时间==>" + LocalDateTime.now());
                System.out.println("task中设定的时间==>" + task);
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("---end--------");
        };
    }

    /**
     * 停止任务
     *
     * @param name
     * @return
     */
    public boolean stop(String name) {
        if (null == taskMap.get(name)) {
            return false;
        }
        ScheduledFuture<?> scheduledFuture = taskMap.get(name);
        scheduledFuture.cancel(true);
        taskMap.remove(name);
        taskList.remove(name);
        return true;
    }
}

这里有一个LocalDateTime转换为Date的工具类是在CommonUtils中的

 public static Date formate(LocalDateTime localDateTime){        ZoneId zoneId = ZoneId.systemDefault();        ZonedDateTime zdt = localDateTime.atZone(zoneId);        Date date = Date.from(zdt.toInstant());        return date;}

任务实体类


@Data
public class Task {
    /**
     * 动态任务名曾
     */
    private String name;

    /**
     * 设定动态任务开始时间
     */
    private LocalDateTime start;
}

想要开启一个动态任务就直接调用DynamicTaskService中的add方法即可

你可能感兴趣的:(开发,spring,boot,java,后端)