package me.ele.marketing.budget.processor.lock;
import lombok.Getter;
import me.ele.napos.vine.misc.exception.UnexpectedStateException;
import me.ele.napos.vine.util.lock.Lock;
import me.ele.napos.vine.util.lock.LockFailedException;
import me.ele.napos.vine.util.lock.LockHandle;
import me.ele.napos.vine.util.lock.internal.LockHandleImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import java.awt.image.Kernel;
import java.io.Closeable;
import java.time.LocalDateTime;
import java.util.concurrent.ThreadLocalRandom;
/**
-
@author: 谢洪伟
-
2021/7/1 5:03 下午
*/
@Service
public class MyRedisLock implements Lock {
@Autowired
private Jedis jedis;
private ThreadLocalRandom random = ThreadLocalRandom.current();@Override
public LockHandle lock(String key) throws LockFailedException {
return null;
}@Override
public LockHandle lock(String key, int expireMills) throws LockFailedException {
return null;
}@Override
public LockHandle lock(String key, int expireMills, int waitMills) throws LockFailedException {
LockHandle handle = new LockHandleImpl(this, key);
if (waitMills > 0) {
LocalDateTime ttl = LocalDateTime.now().plusNanos(waitMills);
do {
String locked = jedis.set(key, handle.getToken(), "nx", "px", waitMills);
if (locked != null) {
return handle;
}
try {
Thread.sleep(random.nextInt(10,100));
} catch (InterruptedException e) {
throw new UnexpectedStateException(e);
}
} while (LocalDateTime.now().isAfter(ttl));
throw new RuntimeException("上锁超时");
}else{
String locked = jedis.set(key, handle.getToken(), "nx", "px", waitMills);
if ( locked != null){
return handle;
}
throw new RuntimeException("上锁失败");
}
}@Override
public void unlock(LockHandle handle) {
String token = jedis.get(handle.getKey());
if (token.equals(handle.getToken())) {
jedis.del(handle.getKey());
}
}public interface Handler extends Closeable {
String getKey();/** * Lock token. */ String getToken(); /** * Release the lock. */ void unlock(); /** * The IOExceptional-off close method. */ @Override default void close() { unlock(); }
}
@Getter
public class HandlerImpl implements Handler {
private Lock lock;
private String key;
private String token;public HandlerImpl(Lock lock, String key) { this.lock = lock; this.key = key; } @Override public String getKey() { return this.key; } @Override public String getToken() { return null; } @Override public void unlock() { lock.unlock(this); }
}
}