Spring定时任务&Springboot异步任务

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();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_42412601/article/details/108492665