4.0.0
com.test
ziyou
0.0.1
redis.clients
jedis
2.4.2
org.apache.commons
commons-pool2
2.2
package com.test.ziyou.common;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
public class JedisManager {
private static JedisPool jedisPool;
static{
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(100);
config.setMaxIdle(10);
config.setMinIdle(0);
jedisPool = new JedisPool(config,"10.47.229.190",6379);
}
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
package com.test.ziyou.lock.distributed;
import com.test.ziyou.common.JedisManager;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by ~~
* 2019/6/3.
*/
public class RedisLock {
public static void main(String[] args) {
testMultiThreadLock();
}
public static void testMultiThreadLock(){
int threadCount = 10;
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 4);
String key = "user:add";
//超时时间
int expire = 1;
for (int i = 0; i < threadCount; i++) {
executorService.execute(() -> {
try {
String lock = RedisLock.tryLock(key, expire);
if (null != lock) {
System.out.println(Thread.currentThread().getName() + "获得锁");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "释放锁");
RedisLock.release(key, lock);
} else {
System.out.println(Thread.currentThread().getName() + "获得锁失败");
}
} catch (Exception e) {
e.printStackTrace();
}
});
}
executorService.shutdown();
}
public static String tryLock(String key, int expire) {
String lockValue = null;
try (Jedis jedis = JedisManager.getJedis()) {
long end = System.currentTimeMillis() + expire;
while (System.currentTimeMillis() < end) {
lockValue = UUID.randomUUID().toString();
Long setnx = jedis.setnx(key, lockValue);
System.out.println(Thread.currentThread().getName() + " 3333 setnx = " + setnx + " , lockValue = " + lockValue);
if (1 == setnx) {
jedis.expire(key, expire);
return lockValue;
}
if (-1 == jedis.ttl(key)) {
jedis.expire(key, expire);
}
}
}
return null;
}
public static boolean release(String key, String value) {
try (Jedis jedis = JedisManager.getJedis()) {
while (true) {
jedis.watch(key);
if (value.equals(jedis.get(key))) {
Transaction transaction = jedis.multi();
jedis.del(key);
List
package com.test.ziyou.lock.distributed;
import com.test.ziyou.common.JedisManager;
import redis.clients.jedis.Jedis;
import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
/**
* Created by ~~
* 2019/6/3.
*/
public class RedisLock2 {
private static final String LOCK_SUCCESS = "OK";
private static final String SET_IF_NOT_EXIST = "NX";
private static final String SET_WITH_EXPIRE_TIME = "PX";
private static final Long RELEASE_SUCCESS = 1L;
/**
* 尝试获取分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param requestId 请求标识
* @param expireTime 超期时间
* @return 是否获取成功
*/
public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
return LOCK_SUCCESS.equals(result);
}
/**
* 释放分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param requestId 请求标识
* @return 是否释放成功
*/
public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
return RELEASE_SUCCESS.equals(result);
}
public static void main(String[] args) {
//要创建的线程的数量
CountDownLatch looker = new CountDownLatch(1);
CountDownLatch latch = new CountDownLatch(10);
final String key = "lockKey";
for (int i = 0; i < latch.getCount(); i++) {
Jedis jedis = JedisManager.getJedis();
UUID uuid = UUID.randomUUID();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
looker.await();
System.out.println(Thread.currentThread().getName() + "竞争资源,获取锁");
boolean getResult = tryGetDistributedLock(jedis, key, uuid.toString(), 5000);
if (getResult) {
System.out.println(Thread.currentThread().getName() + "获取到了锁,处理业务,用时3秒");
Thread.sleep(3000);
boolean releaseResult = releaseDistributedLock(jedis, key, uuid.toString());
if (releaseResult) {
System.out.println(Thread.currentThread().getName() + "业务处理完毕,释放锁");
}
} else {
System.out.println(Thread.currentThread().getName() + "竞争资源失败,未获取到锁");
}
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
}
try {
System.out.println("准备,5秒后开始");
Thread.sleep(5000);
looker.countDown(); //发令 let all threads proceed
latch.await(); // // wait for all to finish
System.out.println("结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* https://www.cnblogs.com/love-wzy/p/10190514.html
*/
/**
* 准备,5秒后开始
*/
/**
* 准备,5秒后开始
* Thread-1竞争资源,获取锁
* Thread-6竞争资源,获取锁
* Thread-9竞争资源,获取锁
* Thread-5竞争资源,获取锁
* Thread-3竞争资源,获取锁
* Thread-4竞争资源,获取锁
* Thread-2竞争资源,获取锁
* Thread-10竞争资源,获取锁
* Thread-8竞争资源,获取锁
* Thread-7竞争资源,获取锁
* Thread-3竞争资源失败,未获取到锁
* Thread-6竞争资源失败,未获取到锁
* Thread-8竞争资源失败,未获取到锁
* Thread-1竞争资源失败,未获取到锁
* Thread-4获取到了锁,处理业务,用时3秒
* Thread-9竞争资源失败,未获取到锁
* Thread-10竞争资源失败,未获取到锁
* Thread-5竞争资源失败,未获取到锁
* Thread-2竞争资源失败,未获取到锁
* Thread-7竞争资源失败,未获取到锁
*/
/**
* 准备,5秒后开始
* Thread-1竞争资源,获取锁
* Thread-6竞争资源,获取锁
* Thread-9竞争资源,获取锁
* Thread-5竞争资源,获取锁
* Thread-3竞争资源,获取锁
* Thread-4竞争资源,获取锁
* Thread-2竞争资源,获取锁
* Thread-10竞争资源,获取锁
* Thread-8竞争资源,获取锁
* Thread-7竞争资源,获取锁
* Thread-3竞争资源失败,未获取到锁
* Thread-6竞争资源失败,未获取到锁
* Thread-8竞争资源失败,未获取到锁
* Thread-1竞争资源失败,未获取到锁
* Thread-4获取到了锁,处理业务,用时3秒
* Thread-9竞争资源失败,未获取到锁
* Thread-10竞争资源失败,未获取到锁
* Thread-5竞争资源失败,未获取到锁
* Thread-2竞争资源失败,未获取到锁
* Thread-7竞争资源失败,未获取到锁
* Thread-4业务处理完毕,释放锁
* 结束
*/
}