CountDownLatch
CountDownLatch与CyclicBarrier有点儿相似。
CyclicBarrier所描述的是“允许一组线程互相等待,直到到达某个公共屏障点,才会进行后续任务”,而CountDownLatch所描述的是”在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待“。在API中是这样描述的:
用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。
其内部实现使用了队列同步器:
private static final class Sync extends AbstractQueuedSynchronizer
构造方法
//有一个参数,计数器,表示线程的数量public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException("count < 0"); this.sync = new Sync(count);}
公共方法
//在计数器变为0或者该线程被中断之前一直保持等待public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1);}//加了等待时间public boolean await(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));}//count减一public void countDown() { sync.releaseShared(1);}//返回当前的count值public long getCount() { return sync.getCount();}
使用实例
还是四个人相约玩游戏,游戏大厅和飞机等待玩家准备,四人都准备了,游戏才开始。
package my.syn;import java.util.concurrent.CountDownLatch;import static my.syn.MyGame.countDownLatch;/** * @ClassName: MyGame * @author: Yang.X.P * @date: 2018-09-17 16:24 **/public class MyGame implements Runnable{ static CountDownLatch countDownLatch = new CountDownLatch(4); @Override public void run() { System.out.println("游戏大厅已加载好,等待所有玩家准备好,即可进入"); try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("所有人到准备好了,游戏开始..."); } public static void main(String[] args){ Player player = new Player(); MyGame myGame = new MyGame(); Aircraft aircraft = new Aircraft(); Thread airThread = new Thread(aircraft); Thread gameThread = new Thread(myGame); gameThread.start(); airThread.start(); for (int i = 0; i < 4; i++) { Thread playerThread = new Thread(player); playerThread.start(); } }}class Aircraft implements Runnable { @Override public void run() { System.out.println("飞机准备好了,等待起飞"); try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("玩家到齐,飞机起飞!"); }}class Player implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "准备好了"); countDownLatch.countDown(); }}
参考资料: