使用ThreadPoolTaskScheduler动态修改调度时间
用
SchedulingConfigurer接口只能统一修改,要分开控制的话有多少个job就要有多少个实现。比较麻烦
配置线程池ThreadPoolTaskScheduler
@Configuration
public class JobConfig {
@Bean("taskExecutor")
public ThreadPoolTaskScheduler taskExecutor() {
ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
executor.setPoolSize(20);
executor.setThreadNamePrefix("taskExecutor-");
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(300);
return executor;
}
}
封装实现
@Component
@Slf4j
public class Jobs {
/**
* key josId
* value ScheduledFuture object
*/
private final ConcurrentHashMap<Integer, ScheduledFuture> jobsMap = new ConcurrentHashMap<>(8);
private final ApplicationContext applicationContext;
private final ThreadPoolTaskScheduler threadPoolTaskScheduler;
private final EcoScheduleJobMapper scheduleJobMapper;
public Jobs(ApplicationContext applicationContext, EcoScheduleJobMapper scheduleJobMapper, ThreadPoolTaskScheduler threadPoolTaskScheduler) {
this.applicationContext = applicationContext;
this.scheduleJobMapper = scheduleJobMapper;
this.threadPoolTaskScheduler = threadPoolTaskScheduler;
init();
}
public Map<Integer, ScheduledFuture> getJobsMap() {
return jobsMap;
}
public void start(Integer jobId) {
if (jobsMap.containsKey(jobId)) {
log.debug("job:{} is running", jobId);
// running...
return;
}
executeJob(selectJobsDetail(jobId));
}
public void stop(Integer jobId) {
ScheduledFuture scheduledFuture = jobsMap.get(jobId);
if (scheduledFuture != null) {
scheduledFuture.cancel(true);
log.debug("job cancel:{}", scheduledFuture);
} else
log.debug("jobId:{} is not running ", jobId);
}
private EcoScheduleJob selectJobsDetail(Integer jobId) {
return scheduleJobMapper.selectByPrimaryKey(jobId);
}
// 修改corn配置,先取消再重新启动
public void reset(Integer jobId) {
ScheduledFuture scheduledFuture = jobsMap.get(jobId);
EcoScheduleJob scheduleJob = selectJobsDetail(jobId);
if (Objects.nonNull(scheduledFuture)) {
scheduledFuture.cancel(true);
log.debug("job:{} cancel success", scheduleJob);
}
if (Objects.nonNull(scheduleJob)) {
executeJob(scheduleJob);
log.debug("job:{} start success", scheduleJob);
}
}
// 启动初始化启动所有job
private void init() {
// 从数据库获取任务信息
List<EcoScheduleJob> jobs = scheduleJobMapper.selectJobs();
if (CollectionUtils.isNotEmpty(jobs)) {
jobs.forEach(this::executeJob);
}
}
private void executeJob(EcoScheduleJob job) {
Runnable runnable = null;
try {
Class<?> clazz = Class.forName(job.getClassName());
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
if (!Arrays.isNullOrEmpty(declaredConstructors)) {
// 只取一个构造器
if (declaredConstructors.length > 1) {
log.warn("{} 存在多个构造器,只能有一个", clazz);
return;
}
Constructor<?> constructor = declaredConstructors[0];
Class<?>[] parameterTypes = constructor.getParameterTypes();
if (parameterTypes.length == 0) {
log.warn("{} 无参构造器", clazz);
return;
}
Class<?> parameterType = parameterTypes[0];
Object bean = applicationContext.getBean(parameterType);
runnable = (Runnable) constructor.newInstance(bean);
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
log.error("任务调度失败:{}", e);
}
if (Objects.nonNull(runnable)) {
ScheduledFuture<?> schedule = threadPoolTaskScheduler.schedule(runnable, new CronTrigger(job.getCron()));
jobsMap.put(job.getJobId(), schedule);
log.debug("job:{} is running...", job);
} else {
log.error("任务调度失败 job Class is null");
}
}
}
pojo
@Table(name = "`eco_schedule_job`")
@Data
public class EcoScheduleJob implements Serializable {
/**
* pk
*/
@Id
@Column(name = "`job_id`")
private Integer jobId;
/**
* 类名
*/
@Column(name = "`class_name`")
private String className;
/**
* cron表达式
*/
@Column(name = "`cron`")
private String cron;
/**
* 状态 1 停用 0 启动
*/
@Column(name = "`status`")
private String status;
}
controller
@RequestMapping("/job")
@RestController
public class ScheduleJobController {
@Reference
private ScheduleJobService scheduleJobService;
@GetMapping("/status.do")
public Object status() {
return scheduleJobService.status();
}
@GetMapping("/start.do")
public Object start(@RequestParam Integer jobId) {
scheduleJobService.start(jobId);
return Response.OK();
}
@GetMapping("/stop.do")
public Object stop(@RequestParam Integer jobId) {
scheduleJobService.stop(jobId);
return Response.OK();
}
@GetMapping("/update.do")
public Object update(@RequestParam Integer jobId, @RequestParam String cron) {
scheduleJobService.update(jobId, cron);
return Response.OK();
}
}
service
@Service
public class ScheduleJobServiceImpl implements ScheduleJobService {
private final EcoScheduleJobMapper ecoScheduleJobMapper;
private final Jobs jobs;
public ScheduleJobServiceImpl(EcoScheduleJobMapper ecoScheduleJobMapper , Jobs jobs) {
this.ecoScheduleJobMapper = ecoScheduleJobMapper;
this.jobs = jobs;
}
@Override
public void update(Integer jobId, String cron) {
EcoScheduleJob scheduleJob = new EcoScheduleJob();
scheduleJob.setJobId(jobId);
scheduleJob.setCron(cron);
ecoScheduleJobMapper.updateByPrimaryKeySelective(scheduleJob);
jobs.reset(jobId);
}
@Override
public void stop(Integer jobId) {
jobs.stop(jobId);
}
@Override
public void start(Integer jobId) {
jobs.start(jobId);
}
@Override
public List<EcoScheduleJob> status() {
Set<Integer> integers = jobs.getJobsMap().keySet();
String join = StringUtils.join(integers, ",");
return ecoScheduleJobMapper.selectByIds(join);
}
}
使用ThreadPoolTaskScheduler动态修改调度时间的更多相关文章
- Python任务调度模块 – APScheduler。动态修改调度时间间隔
APScheduler可以把调度任务放到内存里,也可以把任务放到数据库里,那么如何交互式修改定时任务的执行时间间隔或者下次执行时间呢? 方案一:把定时任务放到数据库里,修改数据库里任务的调度时间 方案 ...
- 动态修改Spring定时器
spring 的Quartz定时器的功能非常强大,可以在特定的年月日小时分秒的时间点触发时间,完成事件的调度,就像windows中得计划任务一样.下面看一个典型的Quartz定时器的实现: 1.首 ...
- Quartz动态改变任务时间
基于quartz-2.2 的动态任务调度 Quartz是一个完全由java编写的开源作业调度框架. 调度器 Quartz框架的核心是调度器.调度器负责管理Quartz应用运行时环境.调度器不是靠自己做 ...
- ArcGIS Server 10.2 实战(二)动态修改要素数据的地理处理服务
上一篇<ArcGIS Server 10.2 实战(一)Asp.net MVC与JSON数据妙用实现动态生成要素图层>介绍了如何用JSON转要素的地理处理服务,实现了动态创建点要素并加载到 ...
- 动态修改 C 语言函数的实现
Objective-C 作为基于 Runtime 的语言,它有非常强大的动态特性,可以在运行期间自省.进行方法调剂.为类增加属性.修改消息转发链路,在代码运行期间通过 Runtime 几乎可以修改 O ...
- Unity 3D动态修改Shader状态,使物体透明等等
Unity动态改Shader状态透明 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- ...
- Linux ulimit和动态修改MySQL最大线程数限制
ulimit是限制进程对资源的使用但软件资源限制变化不大,特别是process/file,分别对应nproc和nofilenproc可用 ulimit -u 查询:nofile可用 ulimit -n ...
- Kafka Java consumer动态修改topic订阅
前段时间在Kafka QQ群中有人问及此事——关于Java consumer如何动态修改topic订阅的问题.仔细一想才发现这的确是个好问题,因为如果简单地在另一个线程中直接持有consumer实例然 ...
- log4j2动态修改日志级别及拓展性使用
一.供参考的完整日志配置 <?xml version="1.0" encoding="UTF-8"?> <!-- 配置LoggerConfig ...
随机推荐
- openvswitch安装与使用
wget http://openvswitch.org/releases/openvswitch-2.4.1.tar.gz tar -xvf openvswitch-2.4.1.tar.gz cd o ...
- 【字符串大模拟】潜伏者—— NOIP2009原题
洛谷连接 就一道黄题没啥可以说的……就是要细心…… 学到了神奇的优化 ios::sync_with_stdio(false); cin优化,能跑的比scanf快!棒!(不过要开std) 这题真的还挺简 ...
- POJ 2528 ——Mayor's posters(线段树+区间操作)
Time limit 1000 ms Memory limit 65536 kB Description The citizens of Bytetown, AB, could not stand t ...
- Python文件的几种读写方式
1). "w "写模式,它是不能读的,如果用w模式打开一个已经存在的文件,会清空以前的文件内容,重新写 "w+ "是读写内容,只要沾上w,肯定会清空原来的文件2 ...
- echats 油表盘 鼠标拖动指针改变数值
近期需要做一个鼠标拖动完成油表盘数值改变的功能,使用canvas感觉太麻烦,而且指针不太好监听和拖动,只能另谋出路,在网上参考了某位大神的操作,最终选择了echats来解决这个问题.废话不多说,直接上 ...
- qt使用QWT注意事项
当继承某个QWT类时,有是使用O_OBJECT弘会出现问题 切记在工程文件里别忘了添加这一句 DEFINES+=QWT_DLL
- 吴恩达深度学习:2.12向量化logistic回归
1.不使用任何for循环用梯度下降实现整个训练集的一步迭代. (0)我们已经讨论过向量化如何显著加速代码,在这次视频中我们会设计向量化是如何实现logistic回归,这样酒桶同时处理m个训练集,来实现 ...
- easyUI解析原理
easyUI通过parser解析器,对页面中的html元素进行查找, 如果查找到class名以easyui-开头的标签,就调用easyui对应的组件,将该标签封装成easyui的组件
- Core Graphics绘图
首先了解一下CGContextRef: An opaque type that represents a Quartz 2D drawing environment. Graphics Context ...
- IDEA启动软件可以选择进入项目而不是直接进入项目
1.File--->Settings 2.Appearance & behavior --->System Settings --->Reopen last project ...