一、导入maven依赖
<!– 操作redis的java客户端jedis –>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
二、代码实现
import java.util.UUID;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
/**
* 分布式锁的思想:多个服务器集群下,只允许其中一个jvm进行操作
* redis实现分布式锁的思路:
*
* 获取锁:在多个jvm情况下,redis实现分布式锁通过setnx方法创建同一个key ,
* 这个key是唯一不重复,如果存入成功返回1获取锁,存入失败返回0,value使用一个唯一不重复的随机数作为线程的ID。
*
* 释放锁:为了保证线程获取的锁,于释放的锁是同一个,在删除reids的key的时候,要对线程ID进行判断,是同一个ID才进行删除
*
* 如何防止死锁
* 1.设置一个获取锁之前的一个时间段,线程如果在这个时间段还没有获取到锁,那么线程就放弃获取锁,返回null
* 2.还要设置另一个时间段,就是线程获取到锁之后,对key设置有效时间,过了这个是时间段,key自动删除 ,释放锁 返回线程ID
*
* @author zxlovey
*
*/
public class LockRedis {
// jedis线程池
private JedisPool jedisPool;
public LockRedis(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
private String reidsKey = “redis_key”;
// 获取锁
/**
*
* @param acquireTimeout
* 获取锁之前的一个时间段
* @param timeOut
* 线程获取到锁之后,对key设置有效时间 一般以秒为单位
*/
public String getLockRedis(Long acquireTimeout, Long timeOut) {
Jedis conn = null;
try {
// 获取到jedis
conn = jedisPool.getResource();
Long endTime = System.currentTimeMillis() + acquireTimeout;
int expireLock = (int) (timeOut / 1000);
String identifierValue = UUID.randomUUID().toString();
while (System.currentTimeMillis() < endTime) {
if (conn.setnx(reidsKey, identifierValue) == 1) {
// 获取锁 设置有效时间
conn.expire(reidsKey, expireLock);
// 返回value,这个value作为线程id 释放锁的时候需要判断删除的key 和获取的锁是同一个
return identifierValue;
}
}
} catch (Exception e) {
// TODO: handle exception
} finally {
if (conn != null) {
conn.close();
}
}
return null;
}
// 释放锁
/**
*
* @param identifierValue
* 锁的ID,就是key 对应的value
*/
public void unLockRedis(String identifierValue) {
Jedis conn = null;
try {
conn = jedisPool.getResource();
if (conn.get(reidsKey).equals(identifierValue)) {
// 获取的key的value相同,说明是同一个线程的锁资源
// 删除key
conn.del(reidsKey);
System.out.println(“释放锁成功:” + Thread.currentThread().getName() + “—锁的ID:” + identifierValue);
}
} catch (Exception e) {
} finally {
if (conn != null) {
conn.close();
}
}
}
}
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class LockServer {
private static JedisPool pool = null;
static {
JedisPoolConfig config = new JedisPoolConfig();
// 设置最大连接数
config.setMaxTotal(200);
// 设置最大空闲数
config.setMaxIdle(8);
// 设置最大等待时间
config.setMaxWaitMillis(1000 * 100);
// 在borrow一个jedis实例时,是否需要验证,若为true,则所有jedis实例均是可用的
config.setTestOnBorrow(true);
pool = new JedisPool(config, “127.0.0.1”, 6379, 3000);
}
private LockRedis lockRedis = new LockRedis(pool);
//演示redis实现分布式锁
public void seckill() {
//1.获取到锁
String identifierValue = lockRedis.getLockRedis(1000L, 1000L);
if(identifierValue == null){
System.out.println(“获取锁失败:”+Thread.currentThread().getName()+”;失败原因是获取锁的时间超时”);
return;
}
System.out.println(“获取锁成功:”+Thread.currentThread().getName()+”—锁的ID:”+identifierValue);
//2.释放锁
lockRedis.unLockRedis(identifierValue);
}
}
public class ThreadLock extends Thread{
private LockServer lockServer;
public ThreadLock(LockServer lockServer) {
this.lockServer = lockServer;
}
@Override
public void run() {
lockServer.seckill();
}
}
public class Test001 {
public static void main(String[] args) {
LockServer lockServer = new LockServer();
for (int i = 0; i < 500; i++) {
ThreadLock tl = new ThreadLock(lockServer);
tl.start();
}
}
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/100803.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...