public class OperateBarrier {
public static final String DROP_BARRIER = "DROP";
public static final String WAIT_BARRIER = "WAIT";
/**
* Barriers
*/
private static ConcurrentHashMap<String, Barrier> barrierMap = new ConcurrentHashMap<>();
private static ConcurrentHashMap<String, Barrier> barrierDropMap = new ConcurrentHashMap<>();
/**
* Active time of barrier unit: second
*/
private static final int BARRIER_EXIST_IN_SECONDS = 10;
private static final Lock lock = new ReentrantLock();
public static <R> R operate(Supplier<R> operate) {
try {
lock.lock();
// 同步执行
return operate.get();
} finally {
lock.unlock();
}
}
public static <R> R operateDropOrWait(String strategy, String operateId, Supplier<R> operateHandel) {
if (DROP_BARRIER.equals(strategy)) {
return operateDrop(operateId, operateHandel);
} else if (WAIT_BARRIER.equals(strategy)) {
return operateWait(operateId, operateHandel);
} else {
return operate(operateHandel);
}
}
/**
* 同一个key、不能重复执行,如果存在重复的,默认5s; 5内只允许一个key执行,如果等待5s后,依旧没有没有获取到锁,就丢弃;
* 采用 semaphore 实现
* @param operateId
* @param operate
* @return
* @param <R>
*/
public static <R> R operateDrop(String operateId, Supplier<R> operate) {
Barrier keyLock = barrierDropMap.computeIfAbsent(operateId, k -> new Barrier(operateId));
// 尝试获取许可,最多等待5秒
boolean acquired = false;
R result = null;
try {
acquired = keyLock.semaphore.tryAcquire(5, TimeUnit.SECONDS);
if (!acquired) {
// 超时后没有获得许可,直接返回
System.out.println("Timeout waiting for semaphore, task not executed by " + Thread.currentThread().getName() + " with key " + operateId);
return null;
}
keyLock.barrierLock.lock();
try {
while (keyLock.isRunning.get()) {
// 如果已经有线程在执行,当前线程等待
keyLock.enQueueCondition.await();
}
keyLock.isRunning.set(true);
try {
// 执行任务
result = operate.get();
} finally {
// 任务执行完毕,重置标志位并唤醒等待的线程
keyLock.isRunning.set(false);
keyLock.enQueueCondition.signal(); // 只唤起一个线程
}
} finally {
keyLock.barrierLock.unlock();
}
} catch (InterruptedException e) {
log.info("operateDrop exception:{}", e);
System.out.println("Thread interrupted ");
Thread.currentThread().interrupt();
} finally {
if (acquired) {
keyLock.semaphore.release();
}
if(!keyLock.semaphore.hasQueuedThreads() && !keyLock.isRunning.get()){
// 任务执行完成后移除operateId对应的Barrier对象
log.info("barrierDropMap release key:{}",operateId);
barrierDropMap.remove(operateId);
}
}
return result;
}
/**
* 等待过期后,如果还没执行完,放弃执行,数据交给下一个,默认是同一个key、等待10秒、如果10秒没有释放,数据就不会执行
* @param operateId
* @param operate
* @return
* @param <R>
*/
public static <R> R operateWait(String operateId, Supplier<R> operate) {
Barrier barrier = barrierMap.computeIfAbsent(operateId, key -> new Barrier(operateId));
boolean signal = inQueue(barrier);
try {
// 同步执行
return operate.get();
} finally {
deQueue(barrier, signal);
}
}
/**
* 功能: 将当前线程加入队列,并判断是否要等待。
* 步骤详解:
* - 获取 barrier.barrierLock 的锁,确保对共享资源的安全访问。
* - 检查当前 Barrier 中的在队列数量,如果大于0,表示有其他线程正在处理,则当前线程需要等待。
* - 使用 await 方法将当前线程挂起,最多等待 BARRIER_EXIST_IN_SECONDS 秒。
* - 增加在队列中的计数器。
* - 释放锁。
* @param barrier
* @return
*/
private static boolean inQueue(Barrier barrier) {
boolean signal = true;
barrier.barrierLock.lock();
try {
// 如果存在队列数,那么当前数据等待10秒,
if (barrier.enQueueCount.get() > 0) {
// 当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态
signal = barrier.enQueueCondition.await(BARRIER_EXIST_IN_SECONDS, TimeUnit.SECONDS);
}
barrier.enQueueCount.incrementAndGet();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
//Ignore
} finally {
barrier.barrierLock.unlock();
}
return signal;
}
/**
* 功能: 从队列中移除当前操作,并处理线程的信号逻辑。
* 步骤详解:
* - 获取 barrier.barrierLock 的锁。
* - 检查在队列中的计数器,如果大于0,并且信号为真,释放一个被阻塞的线程。
* - 减少在队列中的计数器。
* - 如果没有任何线程在等待该条件,则从 barrierMap 中移除该 Barrier 对象。
* - 释放锁。
* @param barrier
* @param signal
*/
private static void deQueue(Barrier barrier, boolean signal) {
barrier.barrierLock.lock();
try {
if (barrier.enQueueCount.get() > 0) {
if (signal) {
// 释放阻塞的线程
barrier.enQueueCondition.signal();
}
barrier.enQueueCount.decrementAndGet();
}
if (!barrier.barrierLock.hasWaiters(barrier.enQueueCondition)) {
barrierMap.remove(barrier.id);
}
} finally {
barrier.barrierLock.unlock();
}
}
private static class Barrier {
private final ReentrantLock barrierLock;
/**
* In queue
*/
private final Condition enQueueCondition;
private String id;
private final AtomicInteger enQueueCount = new AtomicInteger(0);
private final Semaphore semaphore = new Semaphore(1);
private final AtomicBoolean isRunning = new AtomicBoolean(false);
Barrier(String id) {
this.id = id;
barrierLock = new ReentrantLock();
enQueueCondition = barrierLock.newCondition();
}
}
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(100);
for (int i = 1; i < 1000; i++) {
String finalNum = "AAA" + "_";
new Thread(() -> {
// 5 S,释放
String result = OperateBarrier.operateDrop(finalNum, () -> {
try {
System.out.println(Thread.currentThread().getName() + " -> " + finalNum);
int i1 = RandomUtils.nextInt(1, 7) * 1000;
System.out.println(Thread.currentThread().getName() + "sleep " + i1 + "; time" + System.currentTimeMillis());
Thread.sleep(i1);
return "123";
} catch (InterruptedException exception) {
exception.printStackTrace();
}
return finalNum;
});
System.out.println(Thread.currentThread().getName() + "原创“result ------------> :" + result);
}).start();
}
for (int i = 0; i < 100; i++) {
countDownLatch.countDown();
try {
Thread.sleep(1000);
System.out.println("---原创https://blog.csdn.net/Alecor----countDown count:" + countDownLatch.getCount() + "barrierDropMap size:" + barrierDropMap.size());
} catch (InterruptedException exception) {
exception.printStackTrace();
}
}
try {
countDownLatch.await();
} catch (InterruptedException exception) {
exception.printStackTrace();
}
System.out.println("endendendendendend");
}
}