第一步: 添加工具类
package com.common.lock;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import com.danga.MemCached.MemCachedClient;
import com.schooner.MemCached.MemcachedItem;
/**
*
* @ClassName: CacheUtil
* @Description: 缓存工具类
* @author Fanhy
* @date 2014-11-27 上午10:55:39
*
*/
public class CacheUtil
{
/**
* 缓存客户端
*/
private static MemCachedClient memCachedClient;
/**
* 过期时间
*/
private String timeLenght;
/**
* 默认Key的超时时间(小于1000的值,除以1000以后都是0,即永不过期 )
*/
private static Date keyTimeOut;
@SuppressWarnings("unused")
private void init()
{
keyTimeOut = new Date(Integer.parseInt(timeLenght));// 24小时缓存
}
/**
* @MethodName: getKeyCache
* @Description: 获取缓存
* @param keyName 缓存键
* @return 返回数据
*/
public static Object getKeyCache(String keyName)
{
if (null != keyName)
{
MemcachedItem item = memCachedClient.gets(keyName);
if (null != item)
{
return item.getValue();
}
}
return null;
}
/**
* @MethodName: setCache
* @Description: 设置缓存
* @param keyName 缓存主键
* @param value 缓存数据
* @param date 过期时间(new Date(60000)过期时间是60秒)(如不设置默认缓存24小时)(不得超过30天)
*/
public static void setCache(String keyName, Object value, Date date)
{
if (null != keyName && !"".equals(keyName))
{
if (null == date)
{
memCachedClient.set(keyName, value, keyTimeOut);
}
else
{
memCachedClient.set(keyName, value, date);
}
}
}
/**
* @MethodName: setCache
* @Description: 设置缓存
* @param keyName 缓存主键
* @param value 缓存数据
*/
public static void setCache(String keyName, Object value)
{
if (null != keyName && !"".equals(keyName))
{
memCachedClient.set(keyName, value, keyTimeOut);
}
}
/**
* @MethodName: deleteKeyCache
* @Description: 删除缓存
* @param keyName key名称
*/
public static boolean deleteKeyCache(String keyName)
{
if (null != keyName && !"".equals(keyName))
{
return memCachedClient.delete(keyName);
}
return false;
}
public void setMemCachedClient(MemCachedClient memCachedClient)
{
CacheUtil.memCachedClient = memCachedClient;
}
public void setTimeLenght(String timeLenght)
{
this.timeLenght = timeLenght;
}
/**
* @MethodName: addCache
* @Description: 设置缓存不重复Key,暂时只用于分布式同步
* @param keyName
* @param value
* @param date
* @return void 返回类型
*/
public static boolean addCache(String keyName, Object value, Date date)
{
boolean isTrue = false;
if (!StringUtils.isBlank(keyName))
{
if (null == date)
{
Date dt = new Date();
date = DateUtils.addMinutes(dt, 3);
}
isTrue = memCachedClient.add(keyName, value, date);
}
return isTrue;
}
}
第二步 添加Callback 类
package com.common.lock;
/**
* Callback 类
*/
public abstract class Callback<T>
{
public abstract T handle();
}
第三步 添加锁(lock)的公共类
package com.common.lock;
import java.text.MessageFormat;
/**
* 业务锁
*
* 通过 memcache 的 addCache获取锁
*
* @author 820381
*/
public class Lock
{
/**
* 锁
*
* @param lockName
* @return true 成功/false 失败
*/
public static boolean lock(String lockName)
{
return getLock(lockName, 0);
}
/**
* 解除锁
*
* @param lockName
* @return
*/
public static boolean unlock(String lockName)
{
return CacheUtil.deleteKeyCache(lockName);
}
/**
* 锁,并在获得锁的时候执行回调,回调执行完成后,解除锁
*
* @param lockName 锁名
* @param call 回调函数
* @return BusinessRuntimeException: ExceptionCode.CMN_LOCK_FAILED
*/
public static <T> T lock(String lockName, Callback<T> call)
{
if (lock(lockName))
{
try
{
return call.handle();
}
finally
{
unlock(lockName);
}
}
else
{
throw new RuntimeException(MessageFormat.format("Lock [{0}] failed", lockName));
}
}
private static boolean getLock(String lockName, Integer count)
{
boolean gotLock = false;
if (count > 1000)
{
return gotLock;
}
while (true)
{
gotLock = CacheUtil.addCache(lockName, true, null);
if (gotLock)
{
return gotLock;
}
else
{
try
{
Thread.sleep(200);
}
catch (InterruptedException e)
{
// 不处理异常睡眠异常
}
return getLock(lockName, ++count);
}
}
}
}
第四步 方法中调用
public ResultData saveDeliveryorderState(int dohId, int userId,String whCode,boolean type) {
final int dohIdFinal = dohId;
final int userIdFinal = userId;
final String whCodeFinal = whCode;
final boolean ack=type;
final ResultData data = new ResultData();
Lock.lock("PICKED_LOCK" + dohId, new Callback<ResultData>() {
@Override
public ResultData handle() {
try {
String invoceNo=null;
LOGGER.info(String.format("订单 %s 确认打包操作进行锁方法,操作用户ID:%s", dohIdFinal, userIdFinal));
List<Integer> dohIds = new ArrayList<Integer>();
dohIds.add(dohIdFinal);
Map<Integer, Integer> errorMap = doDeliveryorderService.isCanUpdateOrder(dohIds, CommonConstans.DELIVERY_STATUS_FILLORDER);
if (MapUtils.isNotEmpty(errorMap)) {
LOGGER.error(String.format("订单 %s 状态校验不对,操作用户ID:%s", dohIdFinal, userIdFinal));
data.setAck(false);
data.setErrorCode(IMessageConstans.ORDER_STATUS_ERROR);
data.setData(errorMap);
return data;
}
if(ack){
invoceNo = invoiceSerialnoService.getSerialNo();
}
LOGGER.error(String.format("订单 %s 状态校验成功,操作用户ID:%s,开始更新订单状态...", dohIdFinal, userIdFinal));
pickOffService.updateOrderStateByPicked(dohIdFinal, CommonConstans.DELIVERY_STATUS_CONFIRMORDER, userIdFinal,whCodeFinal,invoceNo);
} catch (Exception e) {
LOGGER.error(String.format("订单 %s 状态更新状态失败,操作用户ID:%s", dohIdFinal, userIdFinal));
data.setAck(false);
data.setErrorCode(IMessageConstans.DATABASE_ERROR);
}
return data;
}
});
return data;
}