利用redis的setnx定时分布式锁,核心代码如下:
/**
* 给key上锁,锁的时间长为seconds秒
*
* @param key
* @param seconds
* @return
*/
public static boolean setLock(String key, int seconds) {
Jedis client = getJedis();
if (client == null) {
return false;
}
try {
Long lock = client.setnx(key, "1");
if (lock > 0) {
client.expire(key, seconds);
return true;
}
} catch (Exception e) {
return false;
} finally {
if (null != client) {
client.close();
}
}
return false;
}
下面这个为分布式锁工具类
/**
* @author hyd
*
*/
public class RedisDistributedLock {
//定时补充redisKey过期时间的代码。如果不手动清除这个key或关闭定任务,则会一直进入锁定状态。
public static final Map<String, Timer> timerMap = new Hashtable<>();
//锁前缀
private static final String REDIS_LOCK = "project:distribued:lock:";
// 锁key默认过期时间,单位为分钟
private static final int lockTime = 3 * 60;
}
整体复制代码,好像会出错,我把方法分开写入,您把以下代码复制到工具类中就可以了。
上锁
public static boolean lock(String key, int lockTime) {
String lockKey = REDIS_LOCK + key;
// redisCache是redispool封装的单例
boolean lock = setLock(lockKey, lockTime);
if (lock) {
redisLock(key, lockTime);
return lock;
}
return lock;
}
重载上锁
public static boolean lock(String key){
return lock(key, lockTime);
}
解锁
public static void releaseLock(String key) {
String lockKey = REDIS_LOCK + key;
RedisCache.getInstance().del(lockKey);
Timer timer = timerMap.get(key);
if (timer != null) {
timer.cancel();
}
}
定时补充key时间
public static void redisLock(String key, int lockTime){
String lockKey = REDIS_LOCK + key;
//线程池运行
ThreadPoolUtil.execute(new Runnable() {
@Override
public void run() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
if (timerMap.get(key) != null) {
RedisCache.getInstance().expireLock(lockKey, lockTime);
}
}
}, 10, lockTime * 1000 / 3);
timerMap.put(key, timer);
});
}
}
用法,利用main方法测试如下:
public static void main(String[] args) {
// 不指定时间,默认为3分钟。执行完成后,释放锁。
String key = "reportTimer";
boolean lock = RedisDistributedLock.lock(key);
try {
if (lock) {
timerTask();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
RedisDistributedLock.releaseLock(key);
}
// 不指定时间,默认为3分钟。执行完成后,不释放锁。
String key1 = "reportTimer1";
boolean lock1 = RedisDistributedLock.lock(key1);
try {
if (lock1) {
timerTask();
}
} catch (Exception e) {
e.printStackTrace();
}
// 指定时间,为5分钟。执行完成后,释放锁。
String key2 = "reportTimer2";
boolean lock2 = RedisDistributedLock.lock(key2, 5 * 60);
try {
if (lock2) {
timerTask();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
RedisDistributedLock.releaseLock(key2);
}
// 指定时间,为5分钟。执行完成后,不释放锁。
String key3 = "reportTimer3";
boolean lock3 = RedisDistributedLock.lock(key3, 5 * 60);
try {
if (lock3) {
timerTask();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void timerTask() {
System.out.println("此处为定时任务的逻辑!编写代码时,此处可以删除");
}
以上工具类,适用于项目集群定时任务的执行。具体有什么不懂的,可以私信我。