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. ...
- springboot + @scheduled 多任务并发
一.问题 项目采用springboot搭建,想给方法添加@Scheduled注解,实现两个定时任务.可是运行发现,两个task并没有并发执行,而是执行完一个task才会执行另外一个.上代码: pack ...
- SpringBoot中并发定时任务的实现、动态定时任务的实现(看这一篇就够了)
原创不易,如需转载,请注明出处https://www.cnblogs.com/baixianlong/p/10659045.html,否则将追究法律责任!!! 一.在JAVA开发领域,目前可以通过以下 ...
- spring @Scheduled 并发
一.spring定时任务配置 applicationContext.xml:红色代码部分为需要配置的部分. <?xml version="1.0" encoding=&quo ...
- 集群服务器下使用SpringBoot @Scheduled注解定时任务
原文:https://blog.csdn.net/huyang1990/article/details/78551578 SpringBoot提供了 Schedule模块完美支持定时任务的执行 在实际 ...
- springboot高并发redis细粒度加锁(key粒度加锁)
本文探讨在web开发中如何解决并发访问带来的数据同步问题. 1.需求: 通过REST接口请求并发访问redis,例如:将key=fusor:${order_id} 中的值+1: 2.场景: 设想,多线 ...
- Java SpringBoot Scheduled定时任务
package task.demo.controller; import org.springframework.beans.factory.annotation.Autowired; import ...
- Spring Boot 内置定时任务
启用定时任务 @SpringBootApplication @EnableScheduling // 启动类添加 @EnableScheduling 注解 public class ScheduleD ...
- Java应用多机器部署定时任务解决方案
Java多机部署下定时任务的处理方案. 本文转自:http://www.cnblogs.com/xunianchong/p/6958548.html 需求: 有两台服务器同时部署了同一套代码, 代码中 ...
随机推荐
- 操作系统口令认证,sysdba本地登录需要输入密码
开发测试人员,反馈,sqlplus / as sysdba 登陆需要输入密码? 本篇文档流程: 1.场景还原 2.问题处理 3.相关问题介绍 一.场景还原 1)配置SQLNET.ora配置文件,配置操 ...
- Windows文件夹、文件源代码对比工具--WinMerge
/********************************************************************** * Windows文件夹.文件源代码对比工具--WinM ...
- MacBook使用笔记2 - 安装windows虚拟机攻略
转载请标注原链接:http://www.cnblogs.com/xczyd/p/5498878.html 5月初从阿里滚粗,然后失去了公司发的Mac Air.说实话Mac机器确实比windows好用一 ...
- 初学java集合框架笔记
List接口常用方法: 方法名 说 明 boolean add(Object o) 在列表的末尾顺序添加元素, 起始索引位置从0开始 void add(int index,Object o) 在 ...
- Json序列化,有多对一和多对多关系时出现的问题
/** * 这是一张 单表中的双向一对多,多对一 关系.自己跟自己一对多多对一 */ @Entity @Table(name="tb_test") public class Cre ...
- 面向对象+JAVA基础
泛泛的研究了面向对象的前五章,感觉没有代码的参照理解的知识看过就忘,所以又在推荐下开始了JAVA基础,希望不会鄙视我目前么有一本书能完整看完的记录... public class LeapYear { ...
- hibernate多对多关系
package com.manytomany; import java.util.HashSet; import java.util.Set; public class Student { priva ...
- .NET平台
.nat 是一种跨语言的平台 类跟对象回顾 由于对象归纳类 是归纳对象共性的过程 在类似的基础上 将状态和行为实体话为对象的过程称为实例话 只写属性 只包含set访问器 只读属性 只包含get ...
- Linux-入门配置jdk,tomcat,mysql
Mysql安装 大家可以在这里下 http://mirrors.163.com/mysql/Downloads/MySQL-5.7/ 1)查看CentOS自带的mysql rpm -qa | grep ...
- python的set处理二维数组转一维数组
for splitValue in set(dataset[:, featureIndex].tolist()): 首先set是一个无序,无重复的数据结构,所以很多时候使用它来进行去重:但是set接收 ...