任务锁的实现,同一个任务同一时间只能有一个再执行,不同任务可以同时间执行。加锁键可以用任务名称,组织编码等。
public interface IdempotenceControlService {
/**
* 获取锁
*
* @param lockKey key
* @param timeout 超时时间
* @return 是否成功
*/
boolean acquireLock(String lockKey, long timeout);
/**
* 释放锁
* @param lockKey key
*/
void releaseLock(String lockKey);
}
import org.springframework.stereotype.Service;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
@Service
public class DefaultIdempotenceControlService implements IdempotenceControlService {
private final ConcurrentHashMap<String, LockInfo> lockMap = new ConcurrentHashMap<>();
@Override
public boolean acquireLock(String lockKey, long timeout) {
LockInfo lock = getLock(lockKey);
boolean success;
try {
success = lock.tryLock(timeout, TimeUnit.SECONDS);
} catch (InterruptedException e) {
success = false;
}
if (!success) {
// 如果锁获取失败 则判断该锁是否被其他进程使用
lockMap.computeIfPresent(lockKey, (key, oldLock) -> {
// 看看别的地方有没有用着这个锁
if (oldLock.count.decrementAndGet() == 0) {
// 如果没有 就释放内存
return null;
} else {
return oldLock;
}
});
}
return success;
}
@Override
public void releaseLock(String lockKey) {
lockMap.computeIfPresent(lockKey, (k, lock) -> {
// 释放锁
lock.unlock();
// 看看别的地方有没有用着这个锁
if (lock.count.decrementAndGet() == 0) {
// 如果没有 就释放内存
return null;
} else {
// 否则不管
return lock;
}
});
}
private LockInfo getLock(String lockKey) {
return lockMap.compute(lockKey, (k, lock) -> {
if (lock == null) {
lock = new LockInfo();
}
lock.count.incrementAndGet();
return lock;
});
}
private static class LockInfo extends ReentrantLock {
private static final long serialVersionUID = 692157604638930146L;
public AtomicInteger count = new AtomicInteger(0);
public LockInfo() {
super();
}
}
}