基于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)

Logo

鸿蒙生态一站式服务平台。

更多推荐