package com.seckill.lock;
import com.seckill.redis.RedisClient;
import com.seckill.redis.RedisFactory;
import java.util.Random;
/**
* Created by wuy on 17-2-15.
*/
public class RedisLock {
//納秒和毫秒之間的轉(zhuǎn)換率
public static final long MILLI_NANO_TIME = 1000 * 1000L;
public static final String LOCKED = "TRUE";
public static final Random RANDOM = new Random();
private String key;
//封裝的操作redis的工具
private RedisClient redisClient;
private boolean lock = true;
/**
*
* @param purpose 鎖前綴
* @param key 鎖定的ID等東西
* @param client
*/
public RedisLock(String purpose, String key){
this.key = purpose + "_" + key + "_lock";
this.redisClient = RedisFactory.getDefaultClient();
}
public RedisLock(String purpose, String key,RedisClient client){
this.key = purpose + "_" + key + "_lock";
this.redisClient = RedisFactory.getDefaultClient();
this.redisClient = client;
}
/**
* 加鎖
* 使用方式為:
* lock();
* try{
* ? executeMethod();
* }finally{
* unlock();
* }
* @param timeout timeout的時間范圍內(nèi)輪詢鎖
* @param expire 設(shè)置鎖超時時間
* @return 成功 or 失敗
*/
public boolean lock(long timeout,int expire){
long nanoTime = System.nanoTime();
timeout *= MILLI_NANO_TIME;
try {
//在timeout的時間范圍內(nèi)不斷輪詢鎖
while (System.nanoTime() - nanoTime < timeout) {
//鎖不存在的話,設(shè)置鎖并設(shè)置鎖過期時間,即加鎖
if (this.redisClient.setnx(this.key, LOCKED) == 1) {
this.redisClient.expire(key, expire);//設(shè)置鎖過期時間是為了在沒有釋放
//鎖的情況下鎖過期后消失再来,不會造成永久阻塞
this.lock = true;
return this.lock;
}
System.out.println("出現(xiàn)鎖等待");
//短暫休眠遏佣,避免可能的活鎖
Thread.sleep(3, RANDOM.nextInt(30));
}
} catch (Exception e) {
throw new RuntimeException("locking error",e);
}
return false;
}
public? void unlock() {
try {
if(this.lock){
redisClient.delKey(key);//直接刪除
}
} catch (Throwable e) {
}
}
}
-------------------------