基于redis setnx命令的分布式锁

public class SoaLockSupport {

	private Logger logger = Logger.getLogger(SoaLockSupport.class);
        
        //你的redis实现类
	private RedisAAA redis;

	// 超时时间
	private long timeout = 3000;
	
	/**
	 * 获得锁,如果没拿到,会在超时时间内一直等待
	 */
	public boolean lock(final String key) {
		FutureTask<Boolean> future = new FutureTask<Boolean>(new Callable<Boolean>() {
			public Boolean call() {
				boolean nx = false;
				for (;;) {
					nx = setnx(key);
					if(nx){
						break;
					}
					try {
						// 获取不到暂停2ms
						Thread.sleep(2);
					} catch (InterruptedException e) {
						//
					}
				}
				return nx;
			}
		});
		try {
			return future.get(timeout, TimeUnit.MILLISECONDS);
		} catch (Exception e) {
			logger.error("try lock error,key = "+key, e);
		}
		
		return false;
	}

	/**
	 * 尝试获得锁,如果没拿到,直接返回失败
	 */
	public boolean trylock(String key) {
		if (setnx(key)) {
			return true;
		}

		// 做这一步是防止key一直不被Delete,导致锁一直得不到释放的问题
		String oldTime = redis.getString(key);
		if (oldTime != null && !oldTime.equals("")) {
			long time = Long.valueOf(oldTime) + timeout;
			long now  = System.currentTimeMillis();
			
			if (time < now) {
				logger.info("time = "+time + ",and now="+now);
				redis.delete(key);
				return setnx(key);
			}
		}
		return false;
	}

	/**
	 * 释放锁
	 */
	public void unlock(String key) {
		redis.delete(key);
	}

	private boolean setnx(String key) {
		if (redis.setnx(key, System.currentTimeMillis() + "") == 1) {
			return true;
		}
		return false;
	}

猜你喜欢

转载自supben.iteye.com/blog/2397595