package com.zbkj.common.utils;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.*;
/**
* redis分布式锁
* @author ZXF
* @create 2023/05/10 0010 15:06
* @version
* @注意事项
*/
@Component
public class RedisLockUtil {
private static final ConcurrentHashMap futureMap = new ConcurrentHashMap<>();
//锁过期时间
protected long internalLockLeaseTime = 10L;
//监听锁过期时间
protected long lockListenTime = internalLockLeaseTime + 1L;
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(4);
@Autowired
private RedisUtil redisUtil;
//锁键
private String lock_value = "pasp_lock_value";
//获取锁的超时时间
private long timeout = 5L;
/**
* 开启定时刷新
*/
protected void scheduleExpirationRenewal(String key) {
ScheduledFuture future =
executorService.schedule(new ExpirationRenewal(key), lockListenTime, TimeUnit.SECONDS);
futureMap.put(key, future);
}
/**
* 加锁
*
* @param id
* @return
*/
public boolean lock(String id) {
Long start = System.currentTimeMillis();
for (; ; ) {
//SET命令返回OK ,则证明获取锁成功
boolean lock = redisUtil.setNx(id, lock_value, internalLockLeaseTime);
if (lock) {
scheduleExpirationRenewal(id);
//开启延迟线程,判断10s后是否释放锁,没释放则继续持有锁
return lock;
}
//否则循环等待,在timeout时间内仍未获取到锁,则获取失败
long l = System.currentTimeMillis() - start;
if (l >= timeout) {
return false;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 解锁
*
* @param id
* @return
*/
public void unlock(String id) {
//如果提前释放锁,就删除定时任务
redisUtil.delete(id);
ScheduledFuture future = futureMap.get(id);
if (future != null) {
future.cancel(false);
}
}
public RedisUtil getRedisUtil() {
return redisUtil;
}
/**
* 刷新key的过期时间
*/
private class ExpirationRenewal implements Runnable {
private String key;
public ExpirationRenewal(String key) {
this.key = key;
}
@SneakyThrows
@Override
public void run() {
if (redisUtil.exists(key)) {
System.out.println("执行延迟失效时间中...");
redisUtil.expire(key, internalLockLeaseTime);
}
}
}
}