工具类
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;
/**
* ClassName:RedisUtil
* Description:
*/
public class RedisUtil {
private static final Logger logger = LogManager.getLogger(RedisUtil.class);
// redis连接池
// private static ShardedJedisPool pool;
// static {
// JedisPoolConfig config = new JedisPoolConfig();
// config.setMaxTotal(1000);
// config.setMaxIdle(500);
// config.setMaxWaitMillis(3000);
// config.setTestOnBorrow(true);
// config.setTestOnReturn(true);
// // 集群
// JedisShardInfo jedisShardInfo1 = new JedisShardInfo("127.0.0.1", 6379);
// jedisShardInfo1.setPassword("lianer123456");
// List<JedisShardInfo> list = new LinkedList<JedisShardInfo>();
// list.add(jedisShardInfo1);
// pool = new ShardedJedisPool(config, list);
// }
private static final Integer Lock_Timeout = 3;
private Jedis jedis;
public RedisUtil setJedis(Jedis jedis) {
this.jedis = jedis;
return this;
}
/**
* 外部调用加锁的方法
* @param lockKey 锁的名字
* @param timeout 超时时间(放置时间长度,如:3L)
* @return
*/
public boolean tryLock(String lockKey, Long timeout) {
try {
//获取当前系统时间作为:开始加锁的时间
Long currentTime = System.currentTimeMillis();
// 默认为没有获取到锁
boolean result = false;
// 设置一个死循环,不断去获取锁,直接超过设置的 超时时间 为止
while (true) {
//当前时间超过了设定的超时时间,循环终止
if ((System.currentTimeMillis() - currentTime) / 1000 > timeout) {
break;
} else {
// 通过setnx()和判断上一把锁是否超时,来获取锁。获取则true
result = innerTryLock(lockKey);
if (result) {
break;
} else {
// 休眠0.1秒,降低服务器压力
Thread.sleep(100);
}
}
}
return result;
} catch (Exception e) {
logger.info("e===="+ e);
return false;
}
}
/**
* 释放锁
* @param lockKey 锁的名字
*/
public void realseLock(String lockKey) {
// 如果当前时间已经超过 超时时间,则释放锁
if(!checkIfLockTimeout(System.currentTimeMillis(), lockKey)){
jedis.del(lockKey);
}
}
/**
* 内部获取锁的实现方法
* @param lockKey 锁的名字
* @return
*/
private boolean innerTryLock(String lockKey) {
//当前时间
long currentTime = System.currentTimeMillis();
//设置锁的持续时间
String lockTimeDuration = String.valueOf(currentTime + Lock_Timeout + 1);
Long result = jedis.setnx(lockKey, lockTimeDuration);
if (result == 1) {
return true;
} else {
if (checkIfLockTimeout(currentTime, lockKey)) {
String preLockTimeDuration = jedis.getSet(lockKey, lockTimeDuration);
if (currentTime > Long.valueOf(preLockTimeDuration)) {
return true;
}
}
return false;
}
}
/**
* 判断加锁是否超时
* @param currentTime 当前时间
* @param lockKey 锁的名字
* @return
*/
private boolean checkIfLockTimeout(Long currentTime, String lockKey) {
//如果当前时间超过锁的持续时间,则默认之前的锁已经失效,返回true
if (currentTime > Long.valueOf(jedis.get(lockKey))) {
return true;
} else {
return false;
}
}
}
测试
import redis.clients.jedis.Jedis;
/**
* ClassName:TestRedisLockkey
* Description:
*/
public class TestRedisLockkey {
private static final String lockKey = "Lock_he_hong_qian";
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
RedisUtil redisUtil = new RedisUtil().setJedis(jedis);
try{
// 判断是否获取了锁
boolean getLock = redisUtil.tryLock(lockKey, Long.valueOf(5));
if(getLock){
// 此处可以开始写需要实现的代码
}
}catch(Exception e){
System.out.println(e);
}finally {
// 判断是否超时了,如果未超时,则释放锁。 超时了,锁有可能被其他线程拿走了,就不做任何操作
redisUtil.realseLock(lockKey);
}
}
}