1.启动类启用定时
@SpringBootApplication
@EnableDiscoveryClient
//开启定时任务
@EnableScheduling
public class ShopGoodsApplication {
public static void main(String[] args) {
SpringApplication.run(ShopGoodsApplication.class);
}
}
2. 创建定时任务
@Component
public class TaskTest {
@Autowired
RedisTemplate redisTemplate;
/**
* 定时执行的方法
*
* 使用Redis分布式锁,进行加锁
* 让定时任务 在多台服务器的情况下,只会执行一次
*/
//cron 表达式 执行的时间
@Scheduled(cron = "* * * * * ?")//每秒执行一次
public void taskTest(){
//1.设置加锁 没有的情况下 会返回true,如果有了该key值,则返回false
// 设置成功后 说明持有到锁了 返回true
Boolean task = redisTemplate.opsForValue().setIfAbsent("task", 1);
//2.设置锁的过期时间,防止死锁
redisTemplate.expire("task",30*60, TimeUnit.MINUTES);
if(!task){
//没有争抢(设置)到锁
System.out.println("没有争抢到锁");
return;//方法结束
}
//3.争抢到锁后 执行的逻辑
/**
* 例如:判断Redis中有没num的key
* 有,获取,在本来的基础上加1,然后存入Redis
* 没有,设置num的值为0
*
* 再比如:从Redis中取出,存入数据库等等。
*/
Boolean num = redisTemplate.hasKey("num");
if(num){
//获取
Object num1 = redisTemplate.opsForValue().get("num");
//在本来的基础上加1,然后存入Redis
redisTemplate.opsForValue().set("num",Integer.valueOf(num1.toString())+1);
System.out.println(Integer.valueOf(num1.toString())+1);
}else {
//设置num的值为0
redisTemplate.opsForValue().set("num",0);
}
//4.执行完业务逻辑后,释放锁资源 让其他的线程去争抢锁资源
redisTemplate.delete("task");
}
}
3.启动两个服务测试完事
3.参数说明
@Scheduled 参数可以接受两种定时的设置,一种是我们常用的cron="* * * * * ?",一种是 fixedRate = 1000,两种都表示每隔1秒打印一下内容。
@Scheduled(fixedRate = 6000)
:上一次开始执行时间点之后6秒再执行@Scheduled(fixedDelay = 6000)
:上一次执行完毕时间点之后6秒再执行@Scheduled(initialDelay=1000, fixedRate=6000)
:第一次延迟1秒后执行,之后按fixedRate的规则每6秒执行一次