在redissonLock的lock方法里面,自动实现了续期问题,
可是我们要手动实现怎么办,redisson的续期本质是开启了看门狗线程,所以我们实现这个线程就好了
所以就有了如下代码
@GetMapping("/watchDog")
public String watchDog() {
// 锁的key,实际业务需要拼接
String lockKey = "product_mi10";
// 随机字符,保证释放锁时释放的是自己的锁
String clientId = UUID.randomUUID().toString();
long timeout = 10;
TimeUnit seconds = TimeUnit.SECONDS;
RunnableDemo runnableDemo=null;
try {
// Redis的setnx,加上过期时间,程序还没到释放锁的步骤已经宕机
boolean result=false;
while (!result){
result = redisTemplate.opsForValue().setIfAbsent(lockKey, clientId, timeout, seconds);
}
// Boolean result = this.redisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 10, TimeUnit.SECONDS);
long time= new Date().getTime()+timeout*1000;
runnableDemo = new RunnableDemo(time,redisTemplate,timeout,seconds,lockKey,clientId);
if (!result) {// 保证只有获得锁的线程在执行后续操作
System.out.println("未获取到锁!" + time);
return "结束";
}else {
Thread t1 = new Thread(runnableDemo);
t1.start();
}
// 查询商品库存数
Integer stock = Integer.parseInt(redisTemplate.opsForValue().get("stock"));
if (stock > 0) {
// 减库存操作
Integer realStock = stock - 1;
redisTemplate.opsForValue().set("stock", realStock + "");
System.out.println("扣减成功,剩余库存:" + realStock);
if (realStock==7){
try{
System.out.println("开始休眠");
Thread.sleep(15000);
}catch (Exception e){
}
}
} else {
System.out.println("库存为0,操作失败");
}
} finally {
String s = redisTemplate.opsForValue().get(lockKey);
//判定是不是自己的锁,
if (clientId.equals(s)) {
if (runnableDemo!=null){
runnableDemo.setTime(0);
}
// 释放锁
redisTemplate.delete(lockKey);
}
}
return "执行完毕";
}
线程类
import org.springframework.data.redis.core.RedisTemplate;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class RunnableDemo implements Runnable {
//执行续期的时候需要变更,
private long time;
private RedisTemplate<String, String> redisTemplate;
private long timeout;
private TimeUnit seconds;
private String lockKey;
private String clientId;
@Override
public void run() {
try {
Thread.sleep((timeout / 3) * 1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (time < 1) {
System.out.println("time值为" + time + "不需要执行续期");
} else {
//执行续期
if (redisTemplate.opsForValue().get(lockKey).equals(clientId)) {
//是该线程的key
System.out.println("开始续期");
time = new Date().getTime() + (timeout / 3) * 1000;
redisTemplate.expire(lockKey, timeout, seconds);
run();
} else {
//不是该线程的key
System.out.println("不是该线程的key");
}
}
}
public RunnableDemo(long time, RedisTemplate<String, String> redisTemplate, long timeout, TimeUnit seconds, String lockKey, String clientId) {
this.time = time;
this.redisTemplate = redisTemplate;
this.timeout = timeout;
this.seconds = seconds;
this.lockKey = lockKey;
this.clientId = clientId;
}
public void setTime(long time) {
this.time = time;
}
}
欢迎大家弄出线程池版本,spring代理的异步多线程等各种不同的版本