定时任务调度
最近拿到一个需求,需要在前端配置一些任务,在固定的时间去执行,于是想到可以使用这个方法进行处理,就浅记 一下这个用法
1、配置一个任务调度类,这个类可以直接使用无需修改
/**
* 定时任务调度类
*/
@Component
public class TaskConfig implements SchedulingConfigurer {
private volatile ScheduledTaskRegistrar registrar;
private final ConcurrentHashMap<String, ScheduledFuture<?>> scheduledFutures = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, CronTask> cronTasks = new ConcurrentHashMap<>();
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
//设置10个线程,同时并发执行任务
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(10);
taskScheduler.initialize();
taskRegistrar.setScheduler(taskScheduler);
this.registrar = taskRegistrar;
}
/**
* 修改 cron 需要 调用该方法
*/
public void refresh(List<TaskEntity> tasks, Function<TaskEntity,CronTask> fun){
//取消已经删除的策略任务
Set<String> sids = scheduledFutures.keySet();
for (String sid : sids) {
if(exists(tasks, sid)){
scheduledFutures.get(sid).cancel(true);
}
}
for (TaskEntity taskEntity : tasks) {
String expression = taskEntity.getExpression();
//计划任务表达式为空则跳过
if(ValidateUtil.isEmpty(expression)){
continue;
}
//计划任务已存在并且表达式未发生变化则跳过
if (scheduledFutures.containsKey(taskEntity.getTaskId())
&& cronTasks.get(taskEntity.getTaskId()).getExpression().equals(expression)) {
continue;
}
//业务逻辑处理
CronTask task = fun.apply(taskEntity);
//执行业务
ScheduledFuture<?> future = Objects.requireNonNull(Objects.requireNonNull(registrar.getScheduler())).schedule(task.getRunnable(), task.getTrigger());
cronTasks.put(taskEntity.getTaskId(), task);
assert future != null;
scheduledFutures.put(taskEntity.getTaskId(), future);
}
}
/**
* 停止 cron 运行
*/
public void stop(List<TaskEntity> tasks){
tasks.forEach(item->{
if (scheduledFutures.containsKey(item.getTaskId())) {
// mayInterruptIfRunning设成false话,不允许在线程运行时中断,设成true的话就允许。
scheduledFutures.get(item.getTaskId()).cancel(true);
scheduledFutures.remove(item.getTaskId());
}
});
}
private boolean exists(List<TaskEntity> tasks, String tid){
for(TaskEntity TaskEntity:tasks){
if(TaskEntity.getTaskId().equals(tid)){
return true;
}
}
return false;
}
@PreDestroy
public void destroy() {
this.registrar.destroy();
}
}
2、TaskEntity可以根据你自己的需求进行设置,以下是一个简易的模板
/**
* 定时任务执行类
*/
public class TaskEntity {
/**
* 任务id
*/
private String taskId;
/**
* 任务说明
*/
private String desc;
/**
* cron 表达式
*/
private String expression;
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getExpression() {
return expression;
}
public void setExpression(String expression) {
this.expression = expression;
}
public TaskEntity() {
}
public TaskEntity(String taskId, String desc, String expression) {
this.taskId = taskId;
this.desc = desc;
this.expression = expression;
}
@Override
public String toString() {
return "TaskEntity{" +
"taskId='" + taskId + '\'' +
", desc='" + desc + '\'' +
", expression='" + expression + '\'' +
'}';
}
}
3、具体的业务处理类,根据需求修改
/**
* 定时任务业务处理类
*/
public class TaskHandler implements Function<TaskEntity, CronTask> {
@Override
public CronTask apply(TaskEntity taskEntity) {
return new CronTask(() -> {
//todo-具体的业务代码处理
System.err.println(Thread.currentThread() + "===" + taskEntity.toString());
}, taskEntity.getExpression());
}
}
4、方法调用
List<TaskEntity> list = new ArrayList<>();
list.add(new TaskEntity("taskid", "描述", "0 0/2 * * * ?"));
taskConfig.refresh(list, new TaskHandler());
支持动态添加修改任务,比较高效
测试结果如下: