基于redis简易实现分布式锁(java版)
实现的基本原理
借用redis为外部组件,并且redis2.8后set允许携带参数,所以有以下一个原子性的操作: set [key] [value] ex [m] nx,其中set [key] [value] 是redis中基本的赋值key/value的语句,ex是代表expire(超时)后面的[m]代表的是过期时间,单位是秒,nx的意思是not exists,合起来这句话就是如果redis中不存在键值为[key]的数据则创建,创建成功返回'OK',否则返回空.
下面是案例:
127.0.0.1:6379> set good value ex 3 nx
OK
127.0.0.1:6379> set good value1 ex 3 nx
(nil)
基本思路
1.创建一个基本的锁类
2.创建一个接口用来执行lambda表达式
3.创建一个泛型实体类用来装载携带进lambda表达式的参数
代码
RedisLock.class
package com.example.redis.demo.common;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.params.SetParams;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* redis分布式锁
* @author: zzqayy
* @date: 2020/5/26
*/
public class RedisLock {
/**
* 创建线程池
*/
private final static ThreadPoolExecutor JAVA_POOL = new ThreadPoolExecutor(2, 4, 5, TimeUnit.SECONDS, new ArrayBlockingQueue(4, false));
/**
* 默认加锁时间
*/
private final static int DEFAULT_TIME_INIT_SECOND = -1;
/**
* redis的线程池
*/
private final static JedisPool JEDIS_POOL = new JedisPool();
/**
* redis链接超时时间
*/
private int lockTimeout = DEFAULT_TIME_INIT_SECOND;
/**
* jedis链接客户端
*/
private Jedis jedis;
/**
* 锁的key
*/
private String lockKey;
private RedisLock(){}
/**
* 从池中拿jedis链接
* @return
*/
private static Jedis getJedisInstance(){
return JEDIS_POOL.getResource();
}
/**
* 创建Redis的lock实例
* @param key
* @return
*/
public static RedisLock create(String key){
RedisLock redisLock = new RedisLock();
redisLock.jedis = getJedisInstance();
redisLock.lockKey = key;
return redisLock;
}
/**
* 创建Redis的lock实例
* @param key
* @return
*/
public static RedisLock create(String key, Integer timeout){
RedisLock redisLock = new RedisLock();
redisLock.jedis = getJedisInstance();
redisLock.lockKey = key;
redisLock.lockTimeout = timeout;
return redisLock;
}
/**
* 加锁
* @return
*/
private boolean lock(){
SetParams setParams = SetParams.setParams();
if (lockTimeout != -1){
setParams.ex(lockTimeout);
}
setParams.nx();
return "OK".equals(this.jedis.set(lockKey, "locked", setParams));
}
/**
* 解锁
*/
private void un_lock(){
this.jedis.del(lockKey);
}
/**
* 运行加锁的方法
* @param redisLockFunction
*/
public void exec(RedisLockFunction redisLockFunction){
while (true){
if (this.lock()){
redisLockFunction.runMethod();
this.un_lock();
break;
}
}
}
}
RedisLockFunction.class
package com.example.redis.demo.common;
/**
* redis的运行函数
* @author: zzqayy
* @date: 2020/5/26
*/
public interface RedisLockFunction {
/**
* redis锁运行的方法
*/
void runMethod();
}
RedisLockEntity.class
package com.example.redis.demo.common;
/**
* 装载参数的类
* @author: zzqayy
* @date: 2020/5/27
*/
public class RedisLockEntity {
private T entity;
public T getEntity() {
return entity;
}
public void setEntity(T entity) {
this.entity = entity;
}
public static RedisLockEntityBuilder builder(){
return new RedisLockEntity.RedisLockEntityBuilder();
}
static class RedisLockEntityBuilder{
private T entity;
public RedisLockEntityBuilder(){}
public RedisLockEntity.RedisLockEntityBuilder entityBuilder(T entity){
this.entity = entity;
return this;
}
public RedisLockEntity build(){
RedisLockEntity redisLockEntity = new RedisLockEntity<>();
redisLockEntity.entity = this.entity;
return redisLockEntity;
}
}
}
本地调用实例
public static void main(String[] args) {
Thread thread1 = getTest(1);
Thread thread2 = getTest(2);
Thread thread3 = getTest(3);
Thread thread4 = getTest(4);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
private static Thread getTest(Integer entityInteger){
return JAVA_POOL.getThreadFactory().newThread(() -> {
RedisLock redisLock = RedisLock.create("redisLock");
RedisLockEntity entity = RedisLockEntity
.builder()
.entityBuilder(entityInteger)
.build();
redisLock.exec(() -> {
System.out.println("=================================== " + entity.getEntity() + "开始了 ===================================\n");
for (int i = 0; i < 1000; i++) {
System.out.println(entity.getEntity() + " 的值: " + i);
}
System.out.println("=================================== " + entity.getEntity() + "结束 ===================================\n");
});
});
}
说明:本文内容由zzqayy收集整理或者自己编写,如果存在侵权,请联系站长删除。
吐槽(0)