本文介绍如何使用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 并发的更多相关文章

  1. springboot scheduled并发配置

    本文介绍如何使用springboot的sheduled实现任务的定时调度,并将调度的任务实现为并发的方式. 1.定时调度配置scheduled 1)注册定时任务 package com.xiaoju. ...

  2. springboot + @scheduled 多任务并发

    一.问题 项目采用springboot搭建,想给方法添加@Scheduled注解,实现两个定时任务.可是运行发现,两个task并没有并发执行,而是执行完一个task才会执行另外一个.上代码: pack ...

  3. SpringBoot中并发定时任务的实现、动态定时任务的实现(看这一篇就够了)

    原创不易,如需转载,请注明出处https://www.cnblogs.com/baixianlong/p/10659045.html,否则将追究法律责任!!! 一.在JAVA开发领域,目前可以通过以下 ...

  4. spring @Scheduled 并发

    一.spring定时任务配置 applicationContext.xml:红色代码部分为需要配置的部分. <?xml version="1.0" encoding=&quo ...

  5. 集群服务器下使用SpringBoot @Scheduled注解定时任务

    原文:https://blog.csdn.net/huyang1990/article/details/78551578 SpringBoot提供了 Schedule模块完美支持定时任务的执行 在实际 ...

  6. springboot高并发redis细粒度加锁(key粒度加锁)

    本文探讨在web开发中如何解决并发访问带来的数据同步问题. 1.需求: 通过REST接口请求并发访问redis,例如:将key=fusor:${order_id} 中的值+1: 2.场景: 设想,多线 ...

  7. Java SpringBoot Scheduled定时任务

    package task.demo.controller; import org.springframework.beans.factory.annotation.Autowired; import ...

  8. Spring Boot 内置定时任务

    启用定时任务 @SpringBootApplication @EnableScheduling // 启动类添加 @EnableScheduling 注解 public class ScheduleD ...

  9. Java应用多机器部署定时任务解决方案

    Java多机部署下定时任务的处理方案. 本文转自:http://www.cnblogs.com/xunianchong/p/6958548.html 需求: 有两台服务器同时部署了同一套代码, 代码中 ...

随机推荐

  1. 【草稿】实验室新手HandBook

    PS:本文旨在给初入CV领域实验室的新手一个可供参考的学习列表,使得能够快速熟悉常用且必要的工具.

  2. 本文档教授大家在yii2.0里实现文件上传 首先我们来实现单文件上传

    第一步  首先建立一个关于上传的model层  如果你有已经建好的可以使用表单小部件的model层 也可以直接用这个.在这里我们新建一个新的model层 在model层新建文件  Upload.php ...

  3. maven安装操作

    首先检查我们的系统是否有安装JDK,检验方法:1.首先在我们的“文件资源管理器”地址栏输入cmd.在“文件资源管理器”地址栏输入cmd命令后,按下键盘上的“Enter”键,进入黑科技模式.在我们的“D ...

  4. PythonStudy——字符编码 Character Encoding

    测试一下学习字符编码的问题:解决乱码问题 数据 从 硬盘 => 内存 => cpu应用程序打开文本文件的三步骤1.打开应用程序2.将数据加载到内存中3.cpu将内存中的数据直接翻译成字符显 ...

  5. django中多个app放入同一文件夹apps

    开发IDE:pycharm 新建一个apps文件夹 需要整理的app文件夹拖到同一个文件夹中,即apps.(弹出对话框,取消勾选Search for references) 在pycharm 中,右键 ...

  6. Python微信

    """ Description: 需要提供以下三个信息,在申请到的微信企业号当中可以找到 agentid corpid corpsecret Author:Nod Dat ...

  7. 错误 CS0006 Metadata file 'E:\项目名称\xxxx.dll'

    错误 CS0006 Metadata file 'E:\桌面临时文件\Pos\xxxx.dll' 1.找到这个类库在当前类库右键发生 找到 应用程序-->把程序集名称改成提示错误 的名称 2.找 ...

  8. python网页爬虫开发之六-Selenium使用

    chromedriver禁用图片,禁用js,切换UA selenium 模拟chrome浏览器,此时就是一个真实的浏览器,一个浏览器该加载的该渲染的它都加载都渲染,所以爬取网页的速度很慢.如果可以不加 ...

  9. ScrollView滑动到底部或顶部监听,ScrollView滑动到底部或顶部再继续滑动监听;

    ScrollView滑动到底部或顶部后,再继续滑动达到一定距离的监听: ScrollView滑动到底部或顶部的监听: /** * 监听ScrollView滚动到顶部或者底部做相关事件拦截 */ pub ...

  10. linux如何复制文件夹和移动文件夹

    linux下文件的复制.移动与删除命令为:cp,mv,rm一.文件复制命令cp 命令格式:cp [-adfilprsu] 源文件(source) 目标文件(destination)cp [option ...