除了从AQS开始,您可以使用下面的简单实现。它有些天真(它是同步的,而AQS是无锁算法),但是除非您希望在满足条件的情况下使用它,否则它可能已经足够好了。
public class CountUpAndDownLatch { private CountDownLatch latch; private final Object lock = new Object(); public CountUpAndDownLatch(int count) { this.latch = new CountDownLatch(count); } public void countDownOrWaitIfZero() throws InterruptedException { synchronized(lock) { while(latch.getCount() == 0) { lock.wait(); } latch.countDown(); lock.notifyAll(); } } public void waitUntilZero() throws InterruptedException { synchronized(lock) { while(latch.getCount() != 0) { lock.wait(); } } } public void countUp() { //should probably check for Integer.MAX_VALUE synchronized(lock) { latch = new CountDownLatch((int) latch.getCount() + 1); lock.notifyAll(); } } public int getCount() { synchronized(lock) { return (int) latch.getCount(); } }}注意:我尚未对其进行深入测试,但它的行为似乎与预期的一样:
public static void main(String[] args) throws InterruptedException { final CountUpAndDownLatch latch = new CountUpAndDownLatch(1); Runnable up = new Runnable() { @Override public void run() { try { System.out.println("IN UP " + latch.getCount()); latch.countUp(); System.out.println("UP " + latch.getCount()); } catch (InterruptedException ex) { } } }; Runnable downOrWait = new Runnable() { @Override public void run() { try { System.out.println("IN DOWN " + latch.getCount()); latch.countDownOrWaitIfZero(); System.out.println("DOWN " + latch.getCount()); } catch (InterruptedException ex) { } } }; Runnable waitFor0 = new Runnable() { @Override public void run() { try { System.out.println("WAIT FOR ZERO " + latch.getCount()); latch.waitUntilZero(); System.out.println("ZERO " + latch.getCount()); } catch (InterruptedException ex) { } } }; new Thread(waitFor0).start(); up.run(); downOrWait.run(); Thread.sleep(100); downOrWait.run(); new Thread(up).start(); downOrWait.run();}输出:
IN UP 1UP 2WAIT FOR ZERO 1IN DOWN 2DOWN 1IN DOWN 1ZERO 0DOWN 0IN DOWN 0IN UP 0DOWN 0UP 0



