package com.alecor.Operate;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;
public class OperateBarrier {
private static ConcurrentHashMap<String, Barrier> barrierMap = new ConcurrentHashMap<>();
private static final int BARRIER_EXIST_IN_SECONDS = 5;
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 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);
}
}
private static boolean inQueue(Barrier barrier){
boolean signal = true;
barrier.barrierLock.lock();
try {
if(barrier.enQueueCount.get() > 0){
signal = barrier.enQueueCondition.await(BARRIER_EXIST_IN_SECONDS, TimeUnit.SECONDS);
}
barrier.enQueueCount.incrementAndGet();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally{
barrier.barrierLock.unlock();
}
return 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;
private final Condition enQueueCondition;
private String id;
private final AtomicInteger enQueueCount = new AtomicInteger(0);
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 < 10; i++) {
String finalNum = "AAA" + "_";
new Thread(() ->{
String result = OperateBarrier.operateWait( finalNum,() ->{
try {
System.out.println(Thread.currentThread().getName() + " -> " +finalNum);
Thread.sleep(1000);
} 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("countDownLatch "+ countDownLatch.getCount());
} catch (InterruptedException exception) {
exception.printStackTrace();
}
}
try {
countDownLatch.await();
} catch (InterruptedException exception) {
exception.printStackTrace();
}
System.out.println("endendendendendend");
}
}