使用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 ...
随机推荐
- flowable+tomcat部署flowable项目,在线画流程图
参考: flowable+tomcat部署flowable项目,在线画流程图
- PTA(Basic Level)1011.A+B和C
给定区间 [−231,231] 内的 3 个整数 A.B 和 C,请判断 A+B 是否大于 C. 输入格式: 输入第 1 行给出正整数 T (≤10),是测试用例的个数.随后给出 T 组测试用例,每组 ...
- 【转帖】联芸Maxio展示国产PCIe SSD主控:速度可达3.5GB/s
联芸Maxio展示国产PCIe SSD主控:速度可达3.5GB/s https://www.cnbeta.com/articles/tech/855223.htm 国产主控 紫光做国产颗粒 国产器件对 ...
- python调用jenkinsapi
在通过python 调用jenkinsapi的时候,需要对一些作业进行定时对构建 报错: <title>Error 403 No valid crumb was included in t ...
- mysql 官网下载太慢了,来这里!!!
RT.去官网下载mysql简直是折磨,太慢了!!! 但我还是坚持住了,下载下来了,我自己下载的是 MAC 5.7.27版本,网盘分享下,有需要的自提吧: 链接:https://pan.baidu.co ...
- <<C++ Primer>> 术语表 (总) (待补充)
术语表 目录 第 1 章 开始 第 I 部分 C++基础 第 2 章 变量和基本类型 第 3 章 字符串, 向量和数组 第 4 章 表达式 第 5 章 语句 第 6 章 函数 第 7 章 类 第 II ...
- webelement类的方法
webelement类的方法,常用的汇总如下: clear()清空 例如登录时先清空输入框中的内容 driver.find_element_by_id('username').clear() clic ...
- 786B - Legacy(线段树 + 最短路)线段树优化建图
题意: 就是给定一张n nn个点的图,求源点s ss到每个点的单源最短路.这张图共有q组边,连边方式有3种: a→b ,边权为w的单向边:a→[l,r] ,即a到连续区间[l,r]中的每一个点都有一条 ...
- 【iOS】正則表達式抓取网页数据制作小词典
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/xn4545945/article/details/37684127 应用程序不一定要自己去提供数据. ...
- 基于Graylog的容器日志监控
Docker日志 当一个容器启动的时候,它其实是docker deamon的一个子进程,docker daemon可以拿到容器里面进程的标准输出,然后通过自身的LogDriver模块来处理,LogDr ...