自定义jvm分片锁
/**
* 自定义分片锁
* @Author zyf
* @Date 2022/9/28 14:38
* @Version 1.0
*/
public class WmsLock<K> {
private volatile static WmsLock uniqueInstance;
final ConcurrentHashMap<K, Lock> map = new ConcurrentHashMap<>();
/**
* 是否公平锁
*/
final boolean fair;
/**
* 私有化构造器,保证单例
* 无参构造函数 默认使用非公平锁
*/
private WmsLock() {
fair = false;
}
/**
* 私有化构造器,保证单例
* 有参构造函数指定是否使用公平锁
*
* @param fair 是否公平
*/
private WmsLock(boolean fair) {
this.fair = fair;
}
/**
* 获取实例(默认非公平锁)
* @param
* @return com.irobotics.wms.inventory.lock.WmsLock<?>
* @author zhongyufeng
* @date 2022/9/28 15:32
*/
public static<K> WmsLock<K> getInstance() {
//通过双重判断的方式保证单例
if (uniqueInstance == null) {
synchronized (WmsLock.class){
if (uniqueInstance == null) {
uniqueInstance = new WmsLock<K>();
}
}
}
return uniqueInstance;
}
/**
* 从map里获取锁 如果存在则返回 不存在则创建
* 并使其using++
*
* @param key key
* @return lock
*/
Lock getLock(K key) {
return map.compute(key, (k, lock) -> {
if (lock == null) {
lock = new Lock(fair);
}
lock.using++;
return lock;
});
}
/**
* 获取锁 会阻塞
*
* @param key key
*/
public void lock(K key) {
getLock(key).lock();
}
/**
* 尝试获取锁 不阻塞
*
* @param key key
* @return 获取成功返回true
*/
public boolean tryLock(K key) {
AtomicBoolean b = new AtomicBoolean();
map.compute(key, (k, lock) -> {
if (lock == null) {
lock = new Lock(fair);
}
// 由于tryLock是非阻塞的 我们可以直接在map里进行调用
if (lock.tryLock()) {
// 只有申请成功了才使using++
lock.using++;
// 把结果传递到外部
b.set(true);
}
return lock;
});
return b.get();
}
/**
* 尝试获取锁 并指定时间
*
* @param key key
* @param timeout 过期时间
* @param unit 时间单位
* @return 获取成功返回true
*/
public boolean tryLock(K key, long timeout, TimeUnit unit) {
Lock lock = getLock(key);
boolean b;
try {
b = lock.tryLock(timeout, unit);
} catch (InterruptedException e) {
b = false;
}
if (!b) {
// 如果锁获取失败 则判断该锁是否被其他进程使用
map.computeIfPresent(key, (k, oldLock) -> {
// 看看别的地方有没有用着这个锁
if (--oldLock.using == 0) {
// 如果没有 就释放内存
return null;
} else {
// 否则不管
return oldLock;
}
});
}
return b;
}
/**
* 释放锁 必须由申请锁的线程进行调用
*
* @param key key
*/
public void unlock(K key) {
map.computeIfPresent(key, (k, lock) -> {
// 释放锁
lock.unlock();
// 看看别的地方有没有用着这个锁
if (--lock.using == 0) {
// 如果没有 就释放内存
return null;
} else {
// 否则不管
return lock;
}
});
}
public void lockExecute(K key, Runnable runnable) {
lock(key);
try {
runnable.run();
} finally {
unlock(key);
}
}
public boolean lockExecute(K key, BooleanSupplier supplier) {
lock(key);
try {
return supplier.getAsBoolean();
} finally {
unlock(key);
}
}
public int lockExecute(K key, IntSupplier supplier) {
lock(key);
try {
return supplier.getAsInt();
} finally {
unlock(key);
}
}
public long lockExecute(K key, LongSupplier supplier) {
lock(key);
try {
return supplier.getAsLong();
} finally {
unlock(key);
}
}
public double lockExecute(K key, DoubleSupplier supplier) {
lock(key);
try {
return supplier.getAsDouble();
} finally {
unlock(key);
}
}
public <T> T lockExecute(K key, Supplier<T> supplier) {
lock(key);
try {
return supplier.get();
} finally {
unlock(key);
}
}
public boolean tryLockExecute(K key, Runnable runnable) {
if (tryLock(key)) {
try {
runnable.run();
return true;
} finally {
unlock(key);
}
}
return false;
}
public boolean tryLockExecute(K key, boolean failResult, BooleanSupplier supplier) {
if (tryLock(key)) {
try {
return supplier.getAsBoolean();
} finally {
unlock(key);
}
}
return failResult;
}
public int tryLockExecute(K key, int failResult, IntSupplier supplier) {
if (tryLock(key)) {
try {
return supplier.getAsInt();
} finally {
unlock(key);
}
}
return failResult;
}
public long tryLockExecute(K key, long failResult, LongSupplier supplier) {
if (tryLock(key)) {
try {
return supplier.getAsLong();
} finally {
unlock(key);
}
}
return failResult;
}
public double tryLockExecute(K key, double failResult, DoubleSupplier supplier) {
if (tryLock(key)) {
try {
return supplier.getAsDouble();
} finally {
unlock(key);
}
}
return failResult;
}
public <T> T tryLockExecute(K key, T failResult, Supplier<T> supplier) {
if (tryLock(key)) {
try {
return supplier.get();
} finally {
unlock(key);
}
}
return failResult;
}
public boolean tryLockExecute(K key, BooleanSupplier failSupplier, BooleanSupplier supplier) {
if (tryLock(key)) {
try {
return supplier.getAsBoolean();
} finally {
unlock(key);
}
}
return failSupplier.getAsBoolean();
}
public int tryLockExecute(K key, IntSupplier failSupplier, IntSupplier supplier) {
if (tryLock(key)) {
try {
return supplier.getAsInt();
} finally {
unlock(key);
}
}
return failSupplier.getAsInt();
}
public long tryLockExecute(K key, LongSupplier failSupplier, LongSupplier supplier) {
if (tryLock(key)) {
try {
return supplier.getAsLong();
} finally {
unlock(key);
}
}
return failSupplier.getAsLong();
}
public double tryLockExecute(K key, DoubleSupplier failSupplier, DoubleSupplier supplier) {
if (tryLock(key)) {
try {
return supplier.getAsDouble();
} finally {
unlock(key);
}
}
return failSupplier.getAsDouble();
}
public <T> T tryLockExecute(K key, Supplier<T> failSupplier, Supplier<T> supplier) {
if (tryLock(key)) {
try {
return supplier.get();
} finally {
unlock(key);
}
}
return failSupplier.get();
}
public boolean tryLockExecute(K key, long timeout, Runnable runnable) {
if (tryLock(key, timeout, TimeUnit.MILLISECONDS)) {
try {
runnable.run();
return true;
} finally {
unlock(key);
}
}
return false;
}
public boolean tryLockExecute(K key, long timeout, boolean failResult, BooleanSupplier supplier) {
if (tryLock(key, timeout, TimeUnit.MILLISECONDS)) {
try {
return supplier.getAsBoolean();
} finally {
unlock(key);
}
}
return failResult;
}
public int tryLockExecute(K key, long timeout, int failResult, IntSupplier supplier) {
if (tryLock(key, timeout, TimeUnit.MILLISECONDS)) {
try {
return supplier.getAsInt();
} finally {
unlock(key);
}
}
return failResult;
}
public long tryLockExecute(K key, long timeout, long failResult, LongSupplier supplier) {
if (tryLock(key, timeout, TimeUnit.MILLISECONDS)) {
try {
return supplier.getAsLong();
} finally {
unlock(key);
}
}
return failResult;
}
public double tryLockExecute(K key, long timeout, double failResult, DoubleSupplier supplier) {
if (tryLock(key, timeout, TimeUnit.MILLISECONDS)) {
try {
return supplier.getAsDouble();
} finally {
unlock(key);
}
}
return failResult;
}
public <T> T tryLockExecute(K key, long timeout, T failResult, Supplier<T> supplier) {
if (tryLock(key, timeout, TimeUnit.MILLISECONDS)) {
try {
return supplier.get();
} finally {
unlock(key);
}
}
return failResult;
}
public boolean tryLockExecute(K key, long timeout, BooleanSupplier failSupplier, BooleanSupplier supplier) {
if (tryLock(key, timeout, TimeUnit.MILLISECONDS)) {
try {
return supplier.getAsBoolean();
} finally {
unlock(key);
}
}
return failSupplier.getAsBoolean();
}
public int tryLockExecute(K key, long timeout, IntSupplier failSupplier, IntSupplier supplier) {
if (tryLock(key, timeout, TimeUnit.MILLISECONDS)) {
try {
return supplier.getAsInt();
} finally {
unlock(key);
}
}
return failSupplier.getAsInt();
}
public long tryLockExecute(K key, long timeout, LongSupplier failSupplier, LongSupplier supplier) {
if (tryLock(key, timeout, TimeUnit.MILLISECONDS)) {
try {
return supplier.getAsLong();
} finally {
unlock(key);
}
}
return failSupplier.getAsLong();
}
public double tryLockExecute(K key, long timeout, DoubleSupplier failSupplier, DoubleSupplier supplier) {
if (tryLock(key, timeout, TimeUnit.MILLISECONDS)) {
try {
return supplier.getAsDouble();
} finally {
unlock(key);
}
}
return failSupplier.getAsDouble();
}
public <T> T tryLockExecute(K key, long timeout, Supplier<T> failSupplier, Supplier<T> supplier) {
if (tryLock(key, timeout, TimeUnit.MILLISECONDS)) {
try {
return supplier.get();
} finally {
unlock(key);
}
}
return failSupplier.get();
}
public boolean tryLockExecute(K key, long timeout, TimeUnit unit, Runnable runnable) {
if (tryLock(key, timeout, unit)) {
try {
runnable.run();
return true;
} finally {
unlock(key);
}
}
return false;
}
public boolean tryLockExecute(K key, long timeout, TimeUnit unit, boolean failResult, BooleanSupplier supplier) {
if (tryLock(key, timeout, unit)) {
try {
return supplier.getAsBoolean();
} finally {
unlock(key);
}
}
return failResult;
}
public int tryLockExecute(K key, long timeout, TimeUnit unit, int failResult, IntSupplier supplier) {
if (tryLock(key, timeout, unit)) {
try {
return supplier.getAsInt();
} finally {
unlock(key);
}
}
return failResult;
}
public long tryLockExecute(K key, long timeout, TimeUnit unit, long failResult, LongSupplier supplier) {
if (tryLock(key, timeout, unit)) {
try {
return supplier.getAsLong();
} finally {
unlock(key);
}
}
return failResult;
}
public double tryLockExecute(K key, long timeout, TimeUnit unit, double failResult, DoubleSupplier supplier) {
if (tryLock(key, timeout, unit)) {
try {
return supplier.getAsDouble();
} finally {
unlock(key);
}
}
return failResult;
}
public <T> T tryLockExecute(K key, long timeout, TimeUnit unit, T failResult, Supplier<T> supplier) {
if (tryLock(key, timeout, unit)) {
try {
return supplier.get();
} finally {
unlock(key);
}
}
return failResult;
}
public boolean tryLockExecute(K key, long timeout, TimeUnit unit, BooleanSupplier failSupplier, BooleanSupplier supplier) {
if (tryLock(key, timeout, unit)) {
try {
return supplier.getAsBoolean();
} finally {
unlock(key);
}
}
return failSupplier.getAsBoolean();
}
public int tryLockExecute(K key, long timeout, TimeUnit unit, IntSupplier failSupplier, IntSupplier supplier) {
if (tryLock(key, timeout, unit)) {
try {
return supplier.getAsInt();
} finally {
unlock(key);
}
}
return failSupplier.getAsInt();
}
public long tryLockExecute(K key, long timeout, TimeUnit unit, LongSupplier failSupplier, LongSupplier supplier) {
if (tryLock(key, timeout, unit)) {
try {
return supplier.getAsLong();
} finally {
unlock(key);
}
}
return failSupplier.getAsLong();
}
public double tryLockExecute(K key, long timeout, TimeUnit unit, DoubleSupplier failSupplier, DoubleSupplier supplier) {
if (tryLock(key, timeout, unit)) {
try {
return supplier.getAsDouble();
} finally {
unlock(key);
}
}
return failSupplier.getAsDouble();
}
public <T> T tryLockExecute(K key, long timeout, TimeUnit unit, Supplier<T> failSupplier, Supplier<T> supplier) {
if (tryLock(key, timeout, unit)) {
try {
return supplier.get();
} finally {
unlock(key);
}
}
return failSupplier.get();
}
static final class Lock extends ReentrantLock {
/**
* 正在使用或者是准备使用该锁的数量
*/
int using;
/**
* 锁的有参构造函数
*
* @param fair 是否公平
*/
Lock(boolean fair) {
super(fair);
}
}
}
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 奇怪的阿峰
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果