1.对于定时任务的配置,还是建议配置线程池使用,较好,也可以设置异步线程池;2.定时任务spring提供了SchedulingConfigurer类,并实现里面的方法,看了看源码,它是把每个跑任务的定义为一个类下的一个方法,且也是new出来一个Runnable匿名内部类放进线程池中的。对于Task类是自己定义的,参数 可以按照自己的意愿进行添加修改。
本节代码大致思路,数据库定义一个定时任务表,包含类和方法和cron,然后获取到active=y的任务根据cron来跑。
暂时只是浅浅的研究到这个地步,具体去spring官网:https://docs.spring.io/spring-framework/docs/current/reference/html/integration.html#scheduling。
package com.linkcheers.task.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 定时任务配置
*/
@Configuration
@EnableAsync
@EnableScheduling
public class DynamicTask implements SchedulingConfigurer, AsyncConfigurer{
private final static Logger LOGGER = LoggerFactory.getLogger(DynamicTask.class);
@Bean(destroyMethod = "shutdown", name = "taskScheduler")
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
threadPoolTaskScheduler.setAwaitTerminationSeconds(60);
threadPoolTaskScheduler.setPoolSize(8);
threadPoolTaskScheduler.setThreadNamePrefix("assign-taskScheduled-");
//务必调用此方法来启动
threadPoolTaskScheduler.initialize();
return threadPoolTaskScheduler;
}
/**
* 异步任务执行线程池
* @return
*/
@Bean(destroyMethod = "shutdown",name = "asyncExecutor")
public ThreadPoolTaskExecutor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setQueueCapacity(1000);
executor.setKeepAliveSeconds(600);
executor.setMaxPoolSize(20);
executor.setThreadNamePrefix("assign-async-taskExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
ThreadPoolTaskScheduler taskScheduler = threadPoolTaskScheduler();
scheduledTaskRegistrar.setTaskScheduler(taskScheduler);
}
@Override
public Executor getAsyncExecutor() {
return asyncExecutor();
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (throwable, method, objects) -> {
LOGGER.error("异步任务执行出现异常, message {}, emthod {}, params {}", throwable, method, objects);
};
}
}
package com.linkcheers.task;
import com.linkcheers.config.ApplicationContextHelper;
import com.linkcheers.task.model.TbScheduleTask;
import com.linkcheers.task.service.TbScheduleTaskService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
@Component
public class TaskSchedule implements SchedulingConfigurer{
private static final Logger LOGGER = LoggerFactory.getLogger(TaskSchedule.class);
@Autowired
@Qualifier("taskScheduler")
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
@Autowired
private TbScheduleTaskService taskService;
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
List<TbScheduleTask> list = taskService.activeList();
if(list!=null && list.size()>0){
LOGGER.info("本次启动定时任务"+list.size()+"个........");
list.forEach(s -> {
// schedule方法,周期性执行;execute 执行一次
ScheduledFuture<?> future = threadPoolTaskScheduler.schedule(getTask(s), getTrigger(s));
});
}
}
/**
* Trigger
*
* @param task 任务
* @return Trigger Trigger
*/
private Trigger getTrigger(TbScheduleTask task) {
return new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
CronTrigger trigger = new CronTrigger(task.getCron());
Date nextExec = trigger.nextExecutionTime(triggerContext);
return nextExec;
}
};
}
/**
* runnable
*
* @param task 任务
* @return Runnable
*/
private Runnable getTask(TbScheduleTask task) {
return new Runnable() {
@Override
public void run() {
Class<?> clazz;
try {
clazz = Class.forName(task.getClassName());
String className = lowerFirstCapse(clazz.getSimpleName());
Object bean = ApplicationContextHelper.getBean(className);
Method method = ReflectionUtils.findMethod(bean.getClass(), task.getMethod());
if ("Y".equals(task.getAsync())) {
synchronized (this) {
ReflectionUtils.invokeMethod(method, bean);
}
} else {
ReflectionUtils.invokeMethod(method,bean);
}
} catch (Exception e) {
LOGGER.error("定时任务报错@Exception",e);
}
}
};
}
/**
* 转换首字母小写
*
* @param str
* @return
*/
public static String lowerFirstCapse(String str) {
char[] chars = str.toCharArray();
chars[0] += 32;
return String.valueOf(chars);
}
}
package com.linkcheers.task.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_schedule_task")
public class TbScheduleTask {
@TableId(type = IdType.AUTO)
private Integer id;
@TableField("class_name")
private String className;
private String method;
private String cron;
//是否线程安全
private String async;
private String active;
private String desc;
}