本文介绍如何使用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. System.IO.FileSystemWatcher

    这个类功能很强.可以实时监测文件系统的变化. https://msdn.microsoft.com/zh-cn/library/system.io.filesystemwatcher.aspx 事件 ...

  2. .net webapi跨域方法整理

    方法一 在Web.Config里面加上了配置信息: <httpProtocol> <customHeaders> <add name="Access-Contr ...

  3. java.net.BindException: Address already in use: JVM_Bind:80 异常的解决办法

    今天遇见了这个端口被占用问题 然后各种百度 先是说 用命令 netstat -a -n -o 最后一个选项表示连接所在进程id. 找到8080端口的PID然后打开任务管理器, 切换到进程选项卡, 在菜 ...

  4. hdu5007 Post Robot AC自动机

    DT is a big fan of digital products. He writes posts about technological products almost everyday in ...

  5. Spring的学习和源码的学习

    PS:Spring中有各种的Templeate,比如jdncTemplate,主要是为了避免各种模板的代码,抽象出来的 PS: @Configration.@Bean是用来替代xml那种解析方式 PS ...

  6. Nginx中文url出现404问题

    Nginx中文url出现404问题 前提条件检查,如我的系统centos,需要检查系统字符集是不是支持utf-8, 怎么配置可以参考这个帖子 https://www.vpser.net/manage/ ...

  7. 【转】使用VisualStudio完成自动化C++代码生成和编译工作(GacUI)

    使用VisualStudio完成自动化C++代码生成和编译工作(GacUI)     GacUI终于进入制作dll的阶段了.昨天上传了一个新的工程,在Vczh Library++3.0(E:\Code ...

  8. BCC校验小知识

    BCC校验其实是奇偶校验的一种,但也是经常使用并且效率较高的一种.所谓BCC校验法,就是在发送前和发送后分别把BCC以前包括ETX字符的所有字符按位异或后,按要求变换(增加或去除一个固定的值)后所得到 ...

  9. Ubuntu下三种方法设置环境变量

    一种用于当前终端,一种用于当前用户,一种用于所有用户: 用于当前终端: 在当前终端中输入:export PATH=$PATH:<你的要加入的路径> 不过上面的方法只适用于当前终端,一旦当前 ...

  10. windows server 2008 r2 x64 enterprise service pack1中aspjpeg.dll安装

    官网地址:http://persits.com/ 64位:http://www.persits.com/aspjpeg64.exe sn:lptn9dQO1enAePAXB2wFaCZawYWzfm0 ...