spring自带的定时任务功能@EnableScheduling
1 demo
package com.test.domi.config; import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date; @Component
@Configurable
@EnableScheduling
public class ScheduledTasks {
//每30秒执行一次
@Scheduled(fixedRate = 1000 * 30)
public void reportCurrentTime(){
System.out.println ("Scheduling Tasks Examples: The time is now " + dateFormat ().format (new Date ()));
} //在固定时间执行
@Scheduled(cron = "0 */1 * * * * ")
public void reportCurrentByCron(){
System.out.println ("Scheduling Tasks Examples By Cron: The time is now " + dateFormat ().format (new Date()));
} private SimpleDateFormat dateFormat(){
return new SimpleDateFormat ("HH:mm:ss");
}
}
Scheduling Tasks Examples: The time is now 11:55:54
Scheduling Tasks Examples By Cron: The time is now 11:56:00
Scheduling Tasks Examples: The time is now 11:56:24
Scheduling Tasks Examples: The time is now 11:56:54
Scheduling Tasks Examples By Cron: The time is now 11:57:00
2 详解
http://tramp.cincout.cn/2017/08/18/spring-task-2017-08-18-spring-boot-enablescheduling-analysis/
cron表达式:https://www.zhyd.me/article/43
1.cron是设置定时执行的表达式,如 0 0/5 * * * ?每隔五分钟执行一次
2.zone表示执行时间的时区
3.fixedDelay 和fixedDelayString 一个固定延迟时间执行,上个任务完成后,延迟多久执行
4.fixedRate 和fixedRateString一个固定频率执行,上个任务开始后多长时间后开始执行
5.initialDelay 和initialDelayString表示一个初始延迟时间,第一次被调用前延迟的时间
3 总结常见问题
a: 单线程任务丢失,转为异步线程池
默认的 ConcurrentTaskScheduler 计划执行器采用Executors.newSingleThreadScheduledExecutor() 实现单线程的执行器。因此,对同一个调度任务的执行总是同一个线程。如果任务的执行时间超过该任务的下一次执行时间,则会出现任务丢失,跳过该段时间的任务。上述问题有以下解决办法:
采用异步的方式执行调度任务,配置 Spring 的 @EnableAsync,在执行定时任务的方法上标注 @Async配置任务执行池,线程池大小 n 的数量为 单个任务执行所需时间 / 任务执行的间隔时间。如下:
//每30秒执行一次
@Async("taskExecutor")
@Scheduled(fixedRate = 1000 * 3)
public void reportCurrentTime(){
System.out.println ("线程" + Thread.currentThread().getName() + "开始执行定时任务===&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&7&&&====》"
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
long start = System.currentTimeMillis();
Future<Boolean> isOk1;
Future<Boolean> isOk2;
。 。。。。。。。。。省略。。。。。。。
b: 关于分布式情况下,重复执行的问题(两种方案)
1:可以使用redis的分布式锁保证spring schedule集群只执行一次。 redis分布式锁是通过setnx命令实现的。该命令的作用是,当往redis中存入一个值时,会先判断该值对应的key是否存在,如果存在则返回0,如果不存在,则将该值存入redis并返回1。(但是在分布式跨时区部署的时候,依然无法避免重复执行)
@Component
@Configuration
@EnableScheduling
public class AutoConvertTask {
private static final Logger logger = LoggerFactory.getLogger(AutoConvertTask.class); @Autowired
private RedisTemplate redisTemplate; private static final String LOCK = "task-job-lock"; private static final String KEY = "tasklock"; @Scheduled(cron = "0 0 0 * * ? ")
public void autoConvertJob() {
boolean lock = false;
try {
lock = redisTemplate.opsForValue().setIfAbsent(KEY, LOCK);
logger.info("是否获取到锁:" + lock);
if (lock) {
List<GameHistory> historyList = historyService.findTenDaysAgoUntreated();
for (GameHistory history : historyList) {
update(history);
}
} else {
logger.info("没有获取到锁,不执行任务!");
return;
}
} finally {
if (lock) {
redisTemplate.delete(KEY);
logger.info("任务结束,释放锁!");
} else {
logger.info("没有获取到锁,无需释放锁!");
}
} } }
2:可以通过使用shedlock将spring schedule上锁。详细见:https://segmentfault.com/a/1190000011975027
c: 服务器宕机之后,丢失的任务如何补偿?
可以将每次的任务执行时间缓在redis里,下次执行任务的时候都取出该时间,判断是否为上一个周期,如果不是,可以计算出中间丢失的周期数,然后做响应的补偿操作。如果怕redis宕机,可以将“执行时间”持久化到表中。
spring自带的定时任务功能@EnableScheduling的更多相关文章
- spring自带的定时任务功能,基于注解和xml配置
1.spring的配置文件 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi=&quo ...
- Spring自带的定时任务框架Schedule的优缺点及使用
spring自带的定时任务框架的有点:简单,拆箱即用 spring自带的定时任务框架的缺点: 不支持集群:为避免重复执行的问题 不支持生命周期统一管理:不重启服务情况下关闭,启动任务 不支持分片任务: ...
- SpringBoot定时任务 - Spring自带的定时任务是如何实现的?有何注意点?
通过前文我们基本梳理了定时任务体系:Timer和ScheduledExecutorService是JDK内置的定时任务方案,以及Netty内部基于时间轮实现的HashedWheelTimer,再到Qu ...
- Spring 自带的定时任务
需要几天后,或者某个时间后,定时查询数据.需要用到Spring自带的一个注解 @Scheduled(cron="0/5 * * * * ? ")//每隔5秒钟执行 创建一个clas ...
- Spring 自带的定时任务Scheduled
1.注解@Scheduled 可以作为一个触发源添加到一个方法中,例如,以下的方法将以一个固定延迟时间5秒钟调用一次执行,这个周期是以上一个调用任务的完成时间为基准,在上一个任务完成之后,5s后再次执 ...
- Spring Boot 中实现定时任务的两种方式
在 Spring + SpringMVC 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Qua ...
- spring boot 学习(八)定时任务 @Scheduled
SpringBoot 定时任务 @Scheduled 前言 有时候,我们有这样的需求,需要在每天的某个固定时间或者每隔一段时间让应用去执行某一个任务.一般情况下,可以使用多线程来实现这个功能:在 Sp ...
- spring 缓存(spring自带Cache)(入门)
spring的缓存机制,是方法纬度的缓存机制, 这就意味着我们并不用关注 底层是否使用了数据库以及通过什么方式访问的数据库: 因此,此缓存方法既适用于dao层,也适用于service层. spring ...
- 品Spring:关于@Scheduled定时任务的思考与探索,结果尴尬了
非Spring风格的代码与Spring的结合 现在的开发都是基于Spring的,所有的依赖都有Spring管理,这没有问题. 但是要突然写一些非Spring风格的代码时,可能会很不习惯,如果还要和Sp ...
随机推荐
- 12.2RAC搭建记录
12.2RAC环境搭建记录 安装前资源检查 资源限制要求/etc/security/limits.conf Table 6-1 Installation Owner Resource Limit Re ...
- Java线程的状态分析
线程状态 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于“可运行线程池”中,变得可运行,只 ...
- Java 用HTTP的方式发送JSON报文请求
前言: 项目调用第三方接口时,通常是用socket或者http的通讯方式发送请求:http 为短连接,客户端发送请求都需要服务器端回送响应,请求结束后,主动释放链接.Socket为长连接:通常情况下S ...
- Spring 注解 @Scheduled(cron = "0 0/10 * * * ? ") 动态改变时间
import java.util.Date; import java.util.concurrent.Executor; import java.util.concurrent.Executors; ...
- ReentrantLock可重入锁的原理及使用场景
摘要 从使用场景的角度出发来介绍对ReentrantLock的使用,相对来说容易理解一些. 场景1:如果已加锁,则不再重复加锁 a.忽略重复加锁.b.用在界面交互时点击执行较长时间请求操作时,防止多次 ...
- VS Code 管理 .NET Core解决方案
本练习要使用Visual studio code完成一个包含多个项目的解决方案,包括类库和Web项目.结合Visual Studio Code和.NET Core CLI,创建项目结构如下: pied ...
- mysql 操作sql语句 目录
mysql 操作sql语句 操作数据库 mysql 操作sql语句 操作数据表 mysql 操作sql语句 操作数据表中的内容/记录
- mysql报错Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage
mysql报错Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage 在执行cr ...
- percona顶级项目(针对数据库)
percona顶级项目(针对数据库) 地址:https://github.com/Percona-Lab 1.mongodb_consistent_backupTool for getting con ...
- 右键菜单添加git选项
1.jpg 2.jpg 3.jpg 4.jpg 5.jpg 6.jpg 7.jpg