public class JedisLock {
private Jedis jedis;
private String lockKey;
/**默认过期时间*/
private int expireMillis = 3000;
private String lockValue;
public JedisLock(Jedis jedis, String lockKey){
this.jedis = jedis;
this.lockKey = lockKey;
}
public boolean lock() throws InterruptedException{
return lock(1);
}
public boolean lock(int timeout) throws InterruptedException{
while(timeout > 0){
long expireTm = System.currentTimeMillis()+expireMillis;
String expireTmStr = String.valueOf(expireTm);
if(jedis.setnx(lockKey, expireTmStr)==1){
lockValue = expireTmStr;
return true;
}
String currentValueStr = jedis.get(lockKey);
if(currentValueStr!=null && Long.parseLong(currentValueStr)<System.currentTimeMillis()){
String oldValueStr = jedis.getSet(lockKey, expireTmStr);
if(oldValueStr!=null && oldValueStr.equals(currentValueStr)){
lockValue = expireTmStr;
return true;
}
}
timeout -= 100;
Thread.sleep(100);
}
return false;
}
public void unlock(){
List<String> keys = new ArrayList<String>();
keys.add(lockKey);
List<String> args = new ArrayList<String>();
args.add(lockValue);
//采用lua脚本方式保证在多线程环境下也是原子操作
jedis.eval(
"if (redis.call('exists', KEYS[1]) == 0) then " +
"return -1; " +
"end;" +
"if (redis.call('get', KEYS[1]) == ARGV[1]) then " +
"redis.call('del', KEYS[1]); " +
"return 1;" +
"end; " +
"return 0;"
, keys, args);
}
}