目前有个需求,对于相同的用户同一时间不允许重复操作,于是写了个锁的util。
若之后涉及到集群/多个应用,只需要把内部的锁换成redis/memcache即可.
Util
/**
* 对外暴露的锁Util
* @author Mingchenchen
*
*/
public class LockUtil {
//使用默认的简单锁 长度为128位
private final static SimpleLock LOCK = new SimpleLock(128);
/**
* 加锁
* @param object
* @return
*/
public static boolean addLock(Object object){
return AUTO_DEPLOY_LOCK.add(object);
}
/**
* 移除锁
* @param object
* @return
*/
public static boolean removeLock(Object object){
return AUTO_DEPLOY_LOCK.remove(object);
}
}
/**
* 内部使用的:简单的JAVA自身实现的锁
* @author Mingchenchen
*
*/
public class SimpleLock {
//使用并发HashMap作为单应用lock
private ConcurrentHashMap<Object, Object> lockHashMap;
//锁无需value
private int defaultValue = 1;
protected SimpleLock(int size){
this.lockHashMap = new ConcurrentHashMap<>(size);
}
/**
* 加锁
* 成功true,失败false
* @param object
* @return
*/
protected boolean add(Object object){
//返回值为旧的对象 因此null即是加锁成功 有值则是已经被锁住了
return lockHashMap.putIfAbsent(object, defaultValue) ==null;
}
/**
* 移除锁
* @param object
* @return
*/
protected boolean remove(Object object){
try {
lockHashMap.remove(object);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
具体使用
String userName = "xxx";
boolean addLock = LockUtil.addLock(userName);//加锁
if (!addLock) {//加锁失败 另一个线程相同的用户名正在执行
return ReturnUtil.format(ErrorCodeEnum.DONOT_OPERATE_AGAIN);
}
//加锁成功 进行业务逻辑操作
doSomeThingUseTime();
LockUtil.removeLock(userName);//解锁
另外如果是异步,只需要在run方法里面最后执行完毕解锁即可。