springboot scheduled并发配置
本文介绍如何使用springboot的sheduled实现任务的定时调度,并将调度的任务实现为并发的方式。
1、定时调度配置scheduled
1)注册定时任务
package com.xiaoju.dqa.sentinel.scheduler; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; @Component
public class Scheduler {
private static final Logger logger = LoggerFactory.getLogger(Scheduler.class); @Scheduled(cron = "0 0/2 * * * ?")
public void cronTask() {
long timestamp = System.currentTimeMillis();
try {
Thread thread = Thread.currentThread();
logger.info("cron任务开始, timestamp={}, threadId={}, threadName={}", timestamp, thread.getId(), thread.getName());
Thread.sleep(1000);
} catch (InterruptedException e) {
} } @Scheduled(fixedRate = 2 * 60 )
public void rateTask() {
long timestamp = System.currentTimeMillis();
try {
Thread thread = Thread.currentThread();
logger.info("fixedRate任务开始, timestamp={}, threadId={}, threadName={}", timestamp, thread.getId(), thread.getName());
Thread.sleep(1000);
} catch (InterruptedException e) {
}
} }
2)启动定时任务
package com.xiaoju.dqa.sentinel; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling; @Configuration
@EnableScheduling
@EnableAutoConfiguration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
这里就介绍两种配置调度时间的方式:
1)cron表达式
2)fixedRate,调度频率也就是调度间隔
如下代码中设置的都是每两分钟调度一次。你只需要将任务用@Scheduled装饰即可。
我这里只写了两个调度任务,而且只sleep1s,如果你sleep 10s的话你就能清晰的看到,两个任务是串行执行的。
springboot中定时任务的执行时串行的!
开始把他改成并行的。
2、定时调度并行化
定时调度的并行化,线程池实现,非常简单,只需要添加一个configuration,实现SchedulingConfigurer接口就可以了。
package com.xiaoju.dqa.sentinel.configuration; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; @Configuration
@EnableScheduling
public class ScheduleConfiguration implements SchedulingConfigurer { @Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
} @Bean(destroyMethod="shutdown")
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(100);
}
}
然后你重启服务,可以看到两个任务并行的执行起来。
3、将任务里的方法设置为异步
package com.xiaoju.dqa.sentinel.scheduler; import com.xiaoju.dqa.sentinel.service.AuditCollect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; @Component
public class Scheduler {
private static final Logger logger = LoggerFactory.getLogger(Scheduler.class); @Autowired
private AuditCollect auditCollect; @Scheduled(cron = "0 0/2 * * * ?")
public void cronTask() {
long timestamp = System.currentTimeMillis();
try {
Thread thread = Thread.currentThread();
logger.info("cron任务开始, timestamp={}, threadId={}, threadName={}", timestamp, thread.getId(), thread.getName());
auditCollect.doAuditCollect();
} catch (InterruptedException e) {
} } @Scheduled(fixedRate = 2 * 60 )
public void rateTask() {
long timestamp = System.currentTimeMillis();
try {
Thread thread = Thread.currentThread();
logger.info("fixedRate任务开始, timestamp={}, threadId={}, threadName={}", timestamp, thread.getId(), thread.getName());
auditCollect.doAuditCollect();
} catch (InterruptedException e) {
}
} }
比如这里有个函数执行的是数据收集,可以把他实现为异步的,并同样扔到线程池里并发的执行。
看看是怎么实现的。
package com.xiaoju.dqa.sentinel.service; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xiaoju.dqa.sentinel.client.es.ESDao;
import com.xiaoju.dqa.sentinel.client.es.entity.ESDocument;
import com.xiaoju.dqa.sentinel.client.es.entity.SearchDocument;
import com.xiaoju.dqa.sentinel.client.redis.RedisClient;
import com.xiaoju.dqa.sentinel.mapper.sentinel.SentinelMapper;
import com.xiaoju.dqa.sentinel.model.SentinelClan;
import com.xiaoju.dqa.sentinel.utils.ESSQLUtil;
import com.xiaoju.dqa.sentinel.utils.GlobalStaticConf;
import com.xiaoju.dqa.sentinel.utils.TimeFunction;
import org.elasticsearch.search.SearchHit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component; import java.math.BigDecimal;
import java.util.*; @Component
public class AuditCollect {
protected final Logger logger = LoggerFactory.getLogger(this.getClass()); @Async("sentinelSimpleAsync")
public void doAuditCollect(JSONObject clanObject, long currentTime) {
JSONArray topicArray = clanObject.getJSONArray("families");
// 遍历所有的topic
for (int j = 0; j < topicArray.size(); j++) {
JSONObject topicObject = topicArray.getJSONObject(j);
audit(clanObject, topicObject, currentTime);
}
}
}
可以看到只是用@Async注释一下,并且加入了异步的executor=sentinelSimpleAsync。
SentinelSimpleAsync是我们自己实现来定制化线程池的。
package com.xiaoju.dqa.sentinel.configuration; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor; @Configuration
@EnableAsync
public class ExecutorConfiguration { @Value("${executor.pool.core.size}")
private int corePoolSize;
@Value("${executor.pool.max.size}")
private int maxPoolSize;
@Value("${executor.queue.capacity}")
private int queueCapacity; @Bean
public Executor sentinelSimpleAsync() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix("SentinelSimpleExecutor-");
executor.initialize();
return executor;
} @Bean
public Executor sentinelAsync() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix("SentinelSwapExecutor-"); // rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
配置文件如下:
#============== 线程池 ===================
executor.pool.core.size=100
executor.pool.max.size=150
executor.queue.capacity=2000
想让异步生效的话,只需要在application类上加上EnableAsync注释就好了。
package com.xiaoju.dqa.sentinel; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling; @Configuration
@EnableScheduling
@EnableAutoConfiguration
@EnableAsync
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
springboot scheduled并发配置的更多相关文章
- springboot @scheduled 并发
本文介绍如何使用springboot的sheduled实现任务的定时调度,并将调度的任务实现为并发的方式. 1.定时调度配置scheduled 1)注册定时任务 package com.xiaoju. ...
- EMW 性能优化二之---并发配置
EMW 性能优化二之---并发配置 在前一个日志中写到交货的异步更新,对于RFUI RF的前台操作会提升效率,异步更新不用等待更新状态的返回,启用更新队列的方式执行(SM13). 下面再补全性能相关的 ...
- SpringBoot的自动配置
1.根据条件来装配bean,SpringBoot的自动配置,根据条件进行自动配置. 首先创建一个接口,如下所示: package com.bie.encoding; /** * * @Descript ...
- SpringBoot的自动配置原理
一.入口 上篇注解@SpringBootApplication简单分析,说到了@SpringBootApplication注解的内部结构, 其中@EnableAutoConfiguration利用En ...
- SpringBoot使用Nacos配置中心
本文介绍SpringBoot如何使用阿里巴巴Nacos做配置中心. 1.Nacos简介 Nacos是阿里巴巴集团开源的一个易于使用的平台,专为动态服务发现,配置和服务管理而设计.它可以帮助您轻松构建云 ...
- SpringBoot的Web配置
重写全局配置 如果springboot提供的springmvc配置不符合要求,则可以通过一个配置类(标有@Configuration注解的类)加上@EnableWebMvc注解来实现完全自己控制的mv ...
- springboot系列三、springboot 单元测试、配置访问路径、多个配置文件和多环境配置,项目打包发布
一.单元测试 生成的demo里面包含spring-boot-starter-test :测试模块,包括JUnit.Hamcrest.Mockito,没有的手动加上. <dependency> ...
- 尚硅谷springboot学习23-SpringMVC配置
1. Spring MVC auto-configuration 以下是SpringBoot对SpringMVC的默认配置:(WebMvcAutoConfiguration) Inclusion of ...
- SpringBoot 多环境配置
转载:https://www.cnblogs.com/gdpuzxs/p/7191436.html 在我们的实际开发中,一般都有三套环境,开发环境,测试环境,生产环境,三套环境的数据库连接配置也有所不 ...
随机推荐
- 第二次项目冲刺(Beta阶段)5.22
1.提供当天站立式会议照片一张 会议内容: ①检查前一天的任务情况,将遇到的困难反馈.解决. ②制定新一轮的任务计划. 2.每个人的工作 (1)工作安排 队员 今日进展 明日安排 王婧 #53(完成) ...
- 团队作业8——第二次项目冲刺(Beta阶段)--第七天
会议照片: 燃尽图: 项目进展: 所有项目都已完成 进行app测试即使用情况评估 团队贡献比: 队员 角色 团队贡献比 陈麟凤 PM 17% 张志杰 DEV 18% 黄海鸿 TEST 16% 康建灿 ...
- 201521123023《java程序设计》第四周学习总结
1. 本周学习总结 思维导图 常规: (1)抽象类:不能被直接实例化.只能作为其它类的父类,这一点与final类正好相反.用关键词abstract声明. (2)继承:只能有一个父类,即单继承,子类继承 ...
- 201521123122 《java程序设计》第十四周学习总结
## 201521123122 <java程序设计>第十四周实验总结 ## 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. M ...
- Hyperledger Fabric 1.0 从零开始(三)——环境构建(内网/准离线)
有公网环境的服务器可以直接看 Hyperledger Fabric 1.0 从零开始(二)--环境构建(公网) ,本篇内容与上篇相似,只不过环境搭建需要在内网下,也就是网络被限制的情况下. 1:环境构 ...
- java使用POI操作XWPFDocument 生成Word实战(一)
注:我使用的word 2016功能简介:(1)使用jsoup解析html得到我用来生成word的文本(这个你们可以忽略)(2)生成word.设置页边距.设置页脚(页码),设置页码(文本) 一.解析ht ...
- Java是如何解析xml文件的(DOM)
Java解析xml文件 在Java程序中读取xml文件的过程也称为"解析xml文件": 解析的目的: 获取 节点名和节点值 获取 属性名.属性值. 四中解析方式: DOM SAX ...
- jdk版本切换
安装1.6/1.7/1.8版本的jdk 保存jdk的安装目录下的文件 卸载所有jdk 将jdk各个版本拷贝到一个文件夹下 配置环境变量 因为安装之后系统会有注册表之类的文件,单纯的修改环境是不会修改成 ...
- 静态页面如何实现 include 引入公用代码
一直以来,我司的前端都是用 php 的 include 函数来实现引入 header .footer 这些公用代码的,就像下面这样: <!-- index.php --> <!DOC ...
- webstorm配置scss环境
1.下载 Ruby (安装过程中记得勾选添加到环境变量,安装结束最后可能会弹出一个cmd弹框,可以忽略) 2. cmd安装sass gem install sass 3. cmd检查是否安装 sas ...