**单机版:**CommonLockManager.java
java
package com.xxxxx.xxxxx.common.core.utils;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* 通用本地锁管理器
* 支持:单服务并发场景
*/
public class CommonLockManager {
// 明确使用ReentrantLock作为泛型,而非Lock接口
private static final ConcurrentHashMap<String, ReentrantLock> LOCK_MAP = new ConcurrentHashMap<>();
// 默认锁超时时间(3秒)
public static final long DEFAULT_LOCK_TIMEOUT = 3;
// 私有化构造器,禁止实例化
private CommonLockManager() {
throw new UnsupportedOperationException("工具类禁止实例化");
}
/**
* 构建唯一锁Key:业务类型 + 业务ID(如 "job:1", "plan:2")
*/
private static String buildLockKey(String businessType, Long businessId) {
if (businessType == null || businessType.trim().isEmpty()) {
throw new IllegalArgumentException("业务类型不能为空");
}
if (businessId == null || businessId <= 0) {
throw new IllegalArgumentException("业务ID必须为正整数");
}
return businessType + ":" + businessId;
}
/**
* 获取锁(不存在则自动创建)
*/
private static ReentrantLock getLock(String lockKey) {
// computeIfAbsent:原子创建锁,线程安全
return LOCK_MAP.computeIfAbsent(lockKey, k -> new ReentrantLock());
}
/**
* 尝试获取锁(默认3秒超时)
* @param businessType 业务类型(如 "job", "plan", "pipe")
* @param businessId 业务唯一ID
* @return true=获取成功,false=超时/被占用
*/
public static boolean tryLock(String businessType, Long businessId) {
return tryLock(businessType, businessId, DEFAULT_LOCK_TIMEOUT);
}
/**
* 尝试获取锁(自定义超时)
* @param businessType 业务类型
* @param businessId 业务ID
* @param timeoutSeconds 超时时间(秒)
* @return true=获取成功
*/
public static boolean tryLock(String businessType, Long businessId, long timeoutSeconds) {
String lockKey = buildLockKey(businessType, businessId);
ReentrantLock lock = getLock(lockKey);
try {
// ReentrantLock原生tryLock方法,支持超时
return lock.tryLock(timeoutSeconds, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// 恢复线程中断状态,避免丢失
Thread.currentThread().interrupt();
return false;
}
}
/**
* 释放锁
* 仅当当前线程持有该锁时,才执行释放
*/
public static void unlock(String businessType, Long businessId) {
String lockKey = buildLockKey(businessType, businessId);
ReentrantLock lock = LOCK_MAP.get(lockKey);
// 这里调用ReentrantLock的isHeldByCurrentThread()
if (lock != null && lock.isHeldByCurrentThread()) {
try {
lock.unlock();
} catch (IllegalMonitorStateException e) {
// 防御性编程:避免未持有锁时释放导致的异常
System.err.println("释放锁失败:当前线程未持有锁 " + lockKey);
}
}
}
/**
* 清理未被占用的锁(避免MAP无限膨胀)
*/
public static void cleanUnusedLocks() {
LOCK_MAP.entrySet().removeIf(entry -> {
ReentrantLock lock = entry.getValue();
// 尝试获取锁,能获取到说明无线程占用,可清理
if (lock.tryLock()) {
lock.unlock();
return true;
}
return false;
});
}
}
**分布式版:**CommonLockManager.java
添加Redisson依赖:
XML
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.23.3</version> <!-- 选最新稳定版 -->
</dependency>
java
// 分布式版 CommonLockManager(基于 Redisson)
@Component // 需注入 Spring 容器,因为要依赖 RedissonClient
public class CommonLockManager {
@Resource
private RedissonClient redissonClient;
public static final long DEFAULT_LOCK_TIMEOUT = 3;
private CommonLockManager() {}
private static String buildLockKey(String businessType, Long businessId) {
// 保持原有逻辑不变
}
public static boolean tryLock(String businessType, Long businessId) {
return tryLock(businessType, businessId, DEFAULT_LOCK_TIMEOUT);
}
public boolean tryLock(String businessType, Long businessId, long timeoutSeconds) {
String lockKey = buildLockKey(businessType, businessId);
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(0, timeoutSeconds, TimeUnit.SECONDS); // 0秒等待,超时返回false
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
public void unlock(String businessType, Long businessId) {
String lockKey = buildLockKey(businessType, businessId);
RLock lock = redissonClient.getLock(lockKey);
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}