cron表达式
语法:秒 分 时 日 月 周 年(spring不支持)
http://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html
实例:
在线生成cron表达式:https://cron.qqe2.com/
Springboot整合定时任务和异步任务
定时任务
1、开启定时任务@EnableScheduling
2、@Scheduled 开启一个定时任务
2、自动配置类TaskSchedulingAutoConfiguration
异步任务
1、@EnableAsync开启异步任务
2、@Async给要异步执行的方法标上注解
3、自动配置类TaskExecutionAutoConfiguration
属性绑定在TaskExecutionProperties
底层也是有用到线程池的,默认核心线程数是8,大概看了一下自动配置类,应该是如果系统中没有自定义的线程池,就创建一个新的线程池,如果已经有了,就直接用自定义的线程池
示例:
@Slf4j
@Component
@EnableAsync
@EnableScheduling
public class HelloSchedule {
/**
*1、在spring中cron6位组成,不允许第七位年
*2、在周的位置,1-7代表周一到周日或MON-SUN
*3、定时任务不应该阻塞。默认是阻塞的
* 3.1、可以让业务以异步的方式运行,自己提交到线程池
* 3.2、使用定时任务自带的线程池
* 定时任务自带线程池的线程数:spring.task.scheduling.pool.size=5
* 有些springboot版本设置了这个也不好使,可能是bug
* 3.3、让定时任务异步执行,直接让整个定时任务方法异步执行,而不是方法里的业务异步执行
* springboot提供了异步任务的功能,除了我们自己写一个线程池,把我们自己要执行的
* 业务丢给线程池执行之外,springboot还支持异步任务
* 一、类上加注解@EnableAsync,开启异步任务
* 二、给要异步执行的方法标上注解@Async
*
*
*
*/
@Async
@Scheduled(cron = "* * * ? * 3")
public void hello() throws InterruptedException {
log.info("hello...");
//模拟阻塞,业务执行时间很长
Thread.sleep(3000);
}
}
配置:可以参考TaskExecutionProperties来进行配置
##异步任务设置
spring.task.scheduling.pool.size=5
spring.task.execution.pool.max-size=50
分布式下定时任务的问题
三台机器A1,A2,A3,都有一个定时任务,同一段程序,定时任务的设置都一样,等时间一到,它们就都同时启动了定时任务,就要同时执行业务代码,就会出现幂等性问题
解决:
应该是定时任务,只能有一台机器在执行,不能所有机器同时执行。
使用分布式锁解决。
@Slf4j
@Service
public class seckillSkuScheduled {
@Autowired
private SeckillService seckillService;
@Autowired
private RedissonClient redissionClient;
private final String upload_lock="seckill:upload:lock";
//保证幂等性问题
@Scheduled(cron = "*/5 * * * * ?")
public void uploadSeckillSkuLatest3Days() {
log.info("上架秒杀的商品");
//分布式锁
RLock lock = redissionClient.getLock(upload_lock);
//锁的超时时间
lock.lock(10, TimeUnit.SECONDS);
try{
seckillService.uploadSeckillSkuLatest3Days();
}finally {
//释放锁
lock.unlock();
}
}
}