[Feature] add for new
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package com.github.houbb.lock.api.core;
|
package com.github.houbb.lock.api.core;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -8,4 +9,32 @@ import java.util.concurrent.locks.Lock;
|
|||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
public interface ILock extends Lock {
|
public interface ILock extends Lock {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试加锁
|
||||||
|
* @param time 时间
|
||||||
|
* @param unit 当为
|
||||||
|
* @param key key
|
||||||
|
* @return 返回
|
||||||
|
* @throws InterruptedException 异常
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
boolean tryLock(long time, TimeUnit unit,
|
||||||
|
String key) throws InterruptedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试加锁
|
||||||
|
* @param key key
|
||||||
|
* @return 返回
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
boolean tryLock(String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解锁
|
||||||
|
* @param key key
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
void unlock(String key);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,20 @@
|
|||||||
<artifactId>lock-api</artifactId>
|
<artifactId>lock-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!--============================== INTER ==============================-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.houbb</groupId>
|
||||||
|
<artifactId>id-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.houbb</groupId>
|
||||||
|
<artifactId>wait</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.houbb</groupId>
|
||||||
|
<artifactId>heaven</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!--============================== OTHER ==============================-->
|
<!--============================== OTHER ==============================-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>redis.clients</groupId>
|
<groupId>redis.clients</groupId>
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package com.github.houbb.lock.redis.bs;
|
||||||
|
|
||||||
|
import com.github.houbb.id.api.Id;
|
||||||
|
import com.github.houbb.id.core.core.Ids;
|
||||||
|
import com.github.houbb.lock.api.core.ILock;
|
||||||
|
import com.github.houbb.lock.redis.core.LockRedis;
|
||||||
|
import com.github.houbb.lock.redis.support.operator.IOperator;
|
||||||
|
import com.github.houbb.wait.api.IWait;
|
||||||
|
import com.github.houbb.wait.core.Waits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 引导类
|
||||||
|
* @author binbin.hou
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
public final class LockRedisBs {
|
||||||
|
|
||||||
|
private LockRedisBs(){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 等待实现
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
private IWait wait = Waits.threadSleep();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 等待实现
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
private Id id = Ids.uuid32();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作类
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
private IOperator operator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新建对象实例
|
||||||
|
* @return 对象实例
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
public static LockRedisBs newInstance() {
|
||||||
|
return new LockRedisBs();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockRedisBs wait(IWait wait) {
|
||||||
|
this.wait = wait;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockRedisBs id(Id id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockRedisBs operator(IOperator operator) {
|
||||||
|
this.operator = operator;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建锁
|
||||||
|
* @return 锁
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
public ILock lock() {
|
||||||
|
return new LockRedis(wait, operator, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -45,6 +45,12 @@ public final class LockRedisConst {
|
|||||||
* 暂时定为 30min
|
* 暂时定为 30min
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
public static final long DEFAULT_EXPIRE_MILLS = 1000 * 60 * 30L;
|
public static final int DEFAULT_EXPIRE_MILLS = 1000 * 60 * 30;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认锁为全局锁
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_KEY = "GLOBAL";
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package com.github.houbb.lock.redis.core;
|
||||||
|
|
||||||
|
import com.github.houbb.lock.api.core.ILock;
|
||||||
|
import com.github.houbb.lock.redis.constant.LockRedisConst;
|
||||||
|
import com.github.houbb.wait.api.IWait;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.locks.Condition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 抽象实现
|
||||||
|
* @author binbin.hou
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
public abstract class AbstractLockRedis implements ILock {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 锁等待
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
private final IWait wait;
|
||||||
|
|
||||||
|
protected AbstractLockRedis(IWait wait) {
|
||||||
|
this.wait = wait;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lock() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lockInterruptibly() throws InterruptedException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryLock() {
|
||||||
|
return tryLock(LockRedisConst.DEFAULT_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unlock() {
|
||||||
|
unlock(LockRedisConst.DEFAULT_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryLock(long time, TimeUnit unit, String key) throws InterruptedException {
|
||||||
|
long startTimeMills = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// 一次获取,直接成功
|
||||||
|
boolean result = this.tryLock(key);
|
||||||
|
if(result) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时间判断
|
||||||
|
if(time <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
long durationMills = unit.toMillis(time);
|
||||||
|
long endMills = startTimeMills + durationMills;
|
||||||
|
|
||||||
|
// 循环等待
|
||||||
|
while (System.currentTimeMillis() < endMills) {
|
||||||
|
result = tryLock(key);
|
||||||
|
if(result) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待 10ms
|
||||||
|
wait.wait(TimeUnit.MILLISECONDS, 10);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
|
||||||
|
return tryLock(time, unit, LockRedisConst.DEFAULT_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Condition newCondition() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package com.github.houbb.lock.redis.core;
|
||||||
|
|
||||||
|
import com.github.houbb.heaven.util.lang.StringUtil;
|
||||||
|
import com.github.houbb.id.api.Id;
|
||||||
|
import com.github.houbb.id.core.util.IdThreadLocalHelper;
|
||||||
|
import com.github.houbb.lock.redis.constant.LockRedisConst;
|
||||||
|
import com.github.houbb.lock.redis.exception.LockRedisException;
|
||||||
|
import com.github.houbb.lock.redis.support.operator.IOperator;
|
||||||
|
import com.github.houbb.wait.api.IWait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 这里是基于 redis 实现
|
||||||
|
*
|
||||||
|
* 实际上也可以基于 zk/数据库等实现。
|
||||||
|
*
|
||||||
|
* @author binbin.hou
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
public class LockRedis extends AbstractLockRedis {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* redis 操作实现
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
private final IOperator redisOperator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键标识
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
private final Id id;
|
||||||
|
|
||||||
|
public LockRedis(IWait wait, IOperator redisOperator, Id id) {
|
||||||
|
super(wait);
|
||||||
|
this.redisOperator = redisOperator;
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryLock(String key) {
|
||||||
|
final String requestId = id.id();
|
||||||
|
IdThreadLocalHelper.put(requestId);
|
||||||
|
|
||||||
|
return redisOperator.lock(key, requestId, LockRedisConst.DEFAULT_EXPIRE_MILLS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unlock(String key) {
|
||||||
|
final String requestId = IdThreadLocalHelper.get();
|
||||||
|
if(StringUtil.isEmpty(requestId)) {
|
||||||
|
String threadName = Thread.currentThread().getName();
|
||||||
|
throw new LockRedisException("Thread " + threadName +" not contains requestId");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean unlock = redisOperator.unlock(key, requestId);
|
||||||
|
if(!unlock) {
|
||||||
|
throw new LockRedisException("Unlock key " + key + " result is failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.github.houbb.lock.redis.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author binbin.hou
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
public class LockRedisException extends RuntimeException {
|
||||||
|
|
||||||
|
public LockRedisException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockRedisException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockRedisException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockRedisException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockRedisException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||||
|
super(message, cause, enableSuppression, writableStackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package com.github.houbb.lock.redis.support.redis;
|
package com.github.houbb.lock.redis.support.operator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redis 客户端
|
* Redis 客户端
|
||||||
* @author binbin.hou
|
* @author binbin.hou
|
||||||
* @since 1.0.0
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
public interface IRedisOperator {
|
public interface IOperator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 尝试获取分布式锁
|
* 尝试获取分布式锁
|
||||||
@@ -14,8 +14,9 @@ public interface IRedisOperator {
|
|||||||
* @param requestId 请求标识
|
* @param requestId 请求标识
|
||||||
* @param expireTimeMills 超期时间
|
* @param expireTimeMills 超期时间
|
||||||
* @return 是否获取成功
|
* @return 是否获取成功
|
||||||
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
boolean tryLock(String lockKey, String requestId, int expireTimeMills);
|
boolean lock(String lockKey, String requestId, int expireTimeMills);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解锁
|
* 解锁
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.github.houbb.lock.redis.support.redis.impl;
|
package com.github.houbb.lock.redis.support.operator.impl;
|
||||||
|
|
||||||
import com.github.houbb.lock.redis.constant.LockRedisConst;
|
import com.github.houbb.lock.redis.constant.LockRedisConst;
|
||||||
import com.github.houbb.lock.redis.support.redis.IRedisOperator;
|
import com.github.houbb.lock.redis.support.operator.IOperator;
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -11,7 +11,7 @@ import java.util.Collections;
|
|||||||
* @author binbin.hou
|
* @author binbin.hou
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
public class JedisOperator implements IRedisOperator {
|
public class JedisOperator implements IOperator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* jedis 客户端
|
* jedis 客户端
|
||||||
@@ -37,7 +37,7 @@ public class JedisOperator implements IRedisOperator {
|
|||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean tryLock(String lockKey, String requestId, int expireTimeMills) {
|
public boolean lock(String lockKey, String requestId, int expireTimeMills) {
|
||||||
String result = jedis.set(lockKey, requestId, LockRedisConst.SET_IF_NOT_EXIST, LockRedisConst.SET_WITH_EXPIRE_TIME, expireTimeMills);
|
String result = jedis.set(lockKey, requestId, LockRedisConst.SET_IF_NOT_EXIST, LockRedisConst.SET_WITH_EXPIRE_TIME, expireTimeMills);
|
||||||
return LockRedisConst.LOCK_SUCCESS.equals(result);
|
return LockRedisConst.LOCK_SUCCESS.equals(result);
|
||||||
}
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package com.github.houbb.lock.redis.bs;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 引导类
|
|
||||||
* @author binbin.hou
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
public class LockRedisBs {
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package com.github.houbb.lock.redis.core;
|
|
||||||
|
|
||||||
import com.github.houbb.lock.api.core.ILock;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.locks.Condition;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 抽象实现
|
|
||||||
* @author binbin.hou
|
|
||||||
* @since 0.0.1
|
|
||||||
*/
|
|
||||||
public class AbstractLockRedis implements ILock {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void lock() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void lockInterruptibly() throws InterruptedException {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean tryLock() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unlock() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Condition newCondition() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package com.github.houbb.lock.redis.core;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.locks.Condition;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author binbin.hou
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
public class LockRedis extends AbstractLockRedis {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void lock() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void lockInterruptibly() throws InterruptedException {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean tryLock() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
|
|
||||||
final long timeMills = unit.toMillis(time);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unlock() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Condition newCondition() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package com.github.houbb.lock.redis.support.id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author binbin.hou
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
public interface IId {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回唯一标识
|
|
||||||
* @return 唯一标识
|
|
||||||
*/
|
|
||||||
String id();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package com.github.houbb.lock.redis.support.id.impl;
|
|
||||||
|
|
||||||
import com.github.houbb.lock.redis.support.id.IId;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author binbin.hou
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
public class IdUUID implements IId {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回唯一标识
|
|
||||||
*
|
|
||||||
* @return 唯一标识
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String id() {
|
|
||||||
return UUID.randomUUID().toString().replace("-","");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
16
pom.xml
16
pom.xml
@@ -8,7 +8,7 @@
|
|||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<modules>
|
<modules>
|
||||||
<module>lock-api</module>
|
<module>lock-api</module>
|
||||||
<module>lock-redis</module>
|
<module>lock-core</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@@ -32,7 +32,9 @@
|
|||||||
|
|
||||||
<!--============================== INTER ==============================-->
|
<!--============================== INTER ==============================-->
|
||||||
<plugin.gen.version>1.0.6</plugin.gen.version>
|
<plugin.gen.version>1.0.6</plugin.gen.version>
|
||||||
<heaven.version>0.1.113</heaven.version>
|
<heaven.version>0.1.114</heaven.version>
|
||||||
|
<id.version>0.0.6</id.version>
|
||||||
|
<wait.version>0.0.1</wait.version>
|
||||||
|
|
||||||
<!--============================== OTHER ==============================-->
|
<!--============================== OTHER ==============================-->
|
||||||
<junit.version>4.12</junit.version>
|
<junit.version>4.12</junit.version>
|
||||||
@@ -59,6 +61,16 @@
|
|||||||
<artifactId>heaven</artifactId>
|
<artifactId>heaven</artifactId>
|
||||||
<version>${heaven.version}</version>
|
<version>${heaven.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.houbb</groupId>
|
||||||
|
<artifactId>id-core</artifactId>
|
||||||
|
<version>${id.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.houbb</groupId>
|
||||||
|
<artifactId>wait</artifactId>
|
||||||
|
<version>${wait.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!--============================== OTHER ==============================-->
|
<!--============================== OTHER ==============================-->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
Reference in New Issue
Block a user