MemCached 中获取分布式锁

第一步: 添加工具类

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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值