使用 @Scheduled注解可以快速的设置异步任务
但是只能指定固定的corn不能做到动态修改
业务场景:
当前端传来一个时间,我们需要在这个时间点的时候,执行对应的任务
这时@Scheduled注解就不能满足我们的需要了
我们通过TaskScheduler 的ScheduledFuture> 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方法即可