Spring Schedule定时框架学习笔记,通过该框架可以实现定时任务,按照指定间隔执行指定代码。
文章目录
Spring Schedule简介
什么是Spring Schedule?
作业调度,如定时任务。
Spring Schedule的实现流程
定时关单功能实现流程
- 编辑spring.xml配置文件,增加如下内容:
//IDEA中会出现关联提示,选择结尾是task的driven(观察顶部是否新增了声明,如果有则无需执行第二步) <task:annotation-driven/>
2.(若IDE自动添加了声明,则无需手动更改)新增task相关声明
xmlns:task="http://www.springframework.org/schema/task"
http://www.springframework.org/schema/task
http://ww.springframework.org/schema/task/spring-task.xsd
- 新建task包,创建CloseOrderTask.java类
//类的上一行增加@Component注解 //该方法适合单服务器,不适合集群服务器 @Scheduled(cron="0 */1 * * * ?")//每1分钟执行一次(每个1分钟的整数倍) public void closeOrderTaskV1(){ int hour = Integer.parseInt(PropertiesUtil.getProperty("close.order")); iOrderService.closeOrder(hour); }
- 打断点进行测试。完成
Spring Schedule+Redis分布式锁构建分布式任务调度实现流程
- 编辑spring.xml配置文件,增加如下内容:
//IDEA中会出现关联提示,选择结尾是task的driven(观察顶部是否新增了声明,如果有则无需执行第二步) <task:annotation-driven/>
2.(若IDE自动添加了声明,则无需手动更改)新增task相关声明
xmlns:task="http://www.springframework.org/schema/task"
http://www.springframework.org/schema/task
http://ww.springframework.org/schema/task/spring-task.xsd
- 新建task包,创建CloseOrderTask.java类(该方法有做防死锁问题)
@Scheduled(cron="0 */1 * * * ?") public void closeOrderTaskV2(){ log.info("关闭订单定时任务启动"); long lockTimeout = Long.parseLong(PropertiesUtil.getProperty("lock.timeout","5000")); Long setnxResult = RedisShardedPoolUtil.setnx(Const.REDIS_LOCK_CLOSE_ORDER_TASK_LOCK,String.valueOf(System.currentTimeMillis()+longTimeout)); if(setnxResult != null&&setnxResult.intValue()==1){ //表示设置成功,获取到锁 closeOrder(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK); }else{ //防止死锁 String oldResult = RedisShardedPoolUtil.get(Const.REDIS_LOCK_CLOSE_ORDER_TASK_LOCK); if(oldResult==null||(oldResult!=null&&System.currentTimeMillis()>oldResult)){ String newResult = RedisShardedPoolUtil.getset(Const.REDIS_LOCK_CLOSE_ORDER_TASK_LOCK,String.valueOf(System.currentTimeMillis()+longTimeout)); if(newResult==null||StringUtils.equals(newResult,oldResult)){ closeOrder(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK); }else{ log.info("没有获得分布式锁:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK); } }else{ log.info("没有获得分布式锁:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK); } } log.info("关闭订单定时任务结束"); } private void closeOrder(String lockName){ RedisShardedPoolUtil.expire(locakName,5);//有效期5秒,防止死锁 int hour = Integer.parseInt(PropertiesUtil.getProperty("close.order")); iOrderService.closeOrder(hour); RedisShardedPoolUtil.del(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK); }
- 打断点进行测试。完成
Spring Schedule相关知识
定时任务注解
注解 | 说明 | 例子 |
---|---|---|
@Scheduled | 放在方法的上一行,表明该方法是定时任务,会按照设定的时间自动运行 | @Scheduled(cron=“0 */1 * * * ?”) |
常用cron表达式介绍
表达式 | 说明 |
---|---|
0 0 0 * * ? | 每天0点一次 |
0 0 23 * * ? | 每天23点一次 |
0 */1 * * * ? | 每1分钟(每个1分钟的整数倍) |
0 0 */6 * * ? | 每6小时(每个6小时的整数倍) |
0 0 */1 * * ? | 每1小时(每个1小时的整数倍) |
Cron生成器
通过Cron生成自定义的定时器
MySQL行锁表锁
使用“FOR UPDATE”代表为此次SQL语句增加事务。如果有明确的where,则是行锁。如果是不明确的where,则是表锁。
Redis分布式锁相关命令
Redis命令 | 说明 |
---|---|
setnx | not exists的缩写 |
getset | 先get再set,获取旧的值设置新的值 |
expire | 设置键的有效期 |
del | 删除 |