package com.ctrip.xpipe.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.LockSupport; /** * @author wenchao.meng * <p> * Jun 29, 2018 */ public class Gate { private AtomicBoolean isOpen = new AtomicBoolean(true); private Queue<Thread> passengers = new ConcurrentLinkedDeque<>(); private String name; private static final Logger logger = LoggerFactory.getLogger(Gate.class); public Gate(String name) { this.name = name; } public boolean isOpen() { return isOpen.get(); } public void close() { if (isOpen.compareAndSet(true, false)) { logger.info("[close][{}]", name); } } public void tryPass() { if (isOpen.get()) { return; } if (isOpen.get() == false) { Thread currentThread = Thread.currentThread(); passengers.offer(currentThread); if (isOpen.get() == true) { passengers.remove(currentThread); return; } logger.info("[pass][{}]park", name); LockSupport.park(); logger.info("[pass][{}][park finished]", name); } } public void open() { if (isOpen.compareAndSet(false, true)) { logger.info("[open][{}]", name); makeAllPass(); } } private void makeAllPass() { Thread passenger; while ((passenger = passengers.poll()) != null) { logger.info("[makeAllPass][{}], {}", name, passenger); LockSupport.unpark(passenger); } } @Override public String toString() { return String.format("Gate:%s", name); } }