108 lines
2.8 KiB
Java
108 lines
2.8 KiB
Java
package com.sunyard.util;
|
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.ConcurrentMap;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
|
|
/**
|
|
* IP锁工具类 - 高并发安全实现
|
|
*
|
|
* 为每个IP地址提供唯一的可重入锁,确保同一IP的操作顺序执行
|
|
*/
|
|
public class IpLockUtils {
|
|
|
|
private static final ConcurrentMap<String, ReentrantLock> LOCK_MAP = new ConcurrentHashMap<>();
|
|
|
|
private static final Object CREATION_LOCK = new Object();
|
|
|
|
/**
|
|
* 获取IP对应的锁(保证唯一性)
|
|
* @param ip IP地址
|
|
* @return 可重入锁实例
|
|
*/
|
|
public static ReentrantLock getLockForIp(String ip) {
|
|
ReentrantLock lock = LOCK_MAP.get(ip);
|
|
if (lock != null) {
|
|
return lock;
|
|
}
|
|
|
|
synchronized (CREATION_LOCK) {
|
|
// 双重检查
|
|
lock = LOCK_MAP.get(ip);
|
|
if (lock == null) {
|
|
lock = new ReentrantLock(true); // 公平锁
|
|
LOCK_MAP.put(ip, lock);
|
|
}
|
|
return lock;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 安全加锁(带超时机制)
|
|
* @param ip IP地址
|
|
* @param timeout 超时时间
|
|
* @param unit 时间单位
|
|
* @return 是否成功获取锁
|
|
* @throws InterruptedException
|
|
*/
|
|
public static boolean lockWithTimeout(String ip, long timeout, TimeUnit unit)
|
|
throws InterruptedException {
|
|
|
|
ReentrantLock lock = getLockForIp(ip);
|
|
return lock.tryLock(timeout, unit);
|
|
}
|
|
|
|
/**
|
|
* 解锁指定IP的锁
|
|
* @param ip IP地址
|
|
*/
|
|
public static void unlockForIp(String ip) {
|
|
ReentrantLock lock = LOCK_MAP.get(ip);
|
|
if (lock != null && lock.isHeldByCurrentThread()) {
|
|
lock.unlock();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 清理未使用的锁(可选)
|
|
*/
|
|
public static void cleanupUnusedLocks() {
|
|
LOCK_MAP.entrySet().removeIf(entry ->
|
|
!entry.getValue().isLocked() &&
|
|
entry.getValue().getQueueLength() == 0
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 获取当前锁数量
|
|
*/
|
|
public static int getLockCount() {
|
|
return LOCK_MAP.size();
|
|
}
|
|
|
|
/**
|
|
* 获取IP锁状态
|
|
* @param ip IP地址
|
|
* @return 锁状态字符串
|
|
*/
|
|
public static String getLockStatus(String ip) {
|
|
ReentrantLock lock = LOCK_MAP.get(ip);
|
|
if (lock == null) {
|
|
return "No lock exists";
|
|
}
|
|
|
|
return String.format("Locked: %s, Queue: %d, HoldCount: %d",
|
|
lock.isLocked(), lock.getQueueLength(), lock.getHoldCount());
|
|
}
|
|
|
|
/**
|
|
* 重置所有锁
|
|
*/
|
|
public static void reset() {
|
|
synchronized (CREATION_LOCK) {
|
|
LOCK_MAP.clear();
|
|
}
|
|
}
|
|
}
|