并发工具类系列:java
Java并发工具类(闭锁CountDownLatch)bash
Java并发工具类(栅栏CyclicBarrier)markdown
闭锁是一种同步工具类,能够延迟线程的进度直到其到达终止状态。dom
CountDownLatch是一种灵活的闭锁实现,它能够使一个或者多个线程等待一组事件的发生。ide
闭锁状态包含一个计数器,该计数器被初始化为一个正数,表示须要等待的事件数量。countDown方法递减计数器,表示已经有一个事件已经发生了。而await方法等待计数器达到0,这表示全部须要等待的事件都已经发生。若是计数器的值非0,那么await会一直阻塞直到计数器为0,或者等待中的线程中断或者超时。 下面,咱们以经典的运动员赛跑举例: 工具
n
个,枪响只须要一声,等待的这一声枪响到了,开始门也就打开了,全部运动员开始跑。n
个运动员,直到n为0。下面咱们根据具体的代码来演示CountDownLatch的用法:post
package concurrency; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; class Runner implements Runnable { private static int counter = 0; private final int id = counter++; private static Random rand= new Random(47); private final CountDownLatch start_latch; private final CountDownLatch end_latch; public Runner(CountDownLatch start_latch, CountDownLatch end_latch) { this.start_latch = start_latch; this.end_latch = end_latch; } @Override public void run() { try { start_latch.await(); //全部运动员都在准备状态中,等待教练释放开始门 try { doWork(); //每一个人跑步的时间不一样 end_latch.countDow n(); //跑完后,告诉教练跑完了 } catch (InterruptedException e) { System.out.println("Interrupted Runner" + id); } } catch (InterruptedException e) { System.out.println("Interrupted Runner" + id); } } public void doWork() throws InterruptedException { TimeUnit.MILLISECONDS.sleep(rand.nextInt(2000)); System.out.println(this + "completed"); } @Override public String toString() { return String.format("%1$-3d", id); } } class Coach implements Runnable { private final CountDownLatch start_latch; private final CountDownLatch end_latch; public Coach(CountDownLatch start_latch, CountDownLatch end_latch) { this.start_latch = start_latch; this.end_latch = end_latch; } @Override public void run() { start_latch.countDown(); //教练释放了开始门,运动员们都开始跑 System.out.println("Coach say: Ready!!!! Go!!!!"); try { end_latch.await(); //当结束门的count down减为0时,教练宣布全部人都跑完了。 System.out.println("All runner passed the end point"); } catch (InterruptedException ex) { System.out.println(this + " interrupted"); } } } public class TestRunner { private static final int SIZE = 10; public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); CountDownLatch startGate = new CountDownLatch(1); CountDownLatch endGate = new CountDownLatch(SIZE); for (int i = 0; i < SIZE; i++) { exec.execute(new Runner(startGate, endGate)); } exec.execute(new Coach(startGate, endGate)); exec.shutdown(); } } 复制代码
CountDownLatch强调的是一个线程(或多个)须要等待另外的n个线程干完某件事情以后才能继续执行。 上述例子,Coach线程是裁判,10个Runner是跑步的。运动员先准备,裁判喊跑,运动员才开始跑(这是第一次同步,对应startGate)。10我的谁跑到终点了,countdown一下,直到10我的所有到达,裁判喊停(这是第二次同步,对应endGate)。 最后运行结果以下:this
Coach say: Ready!!!! Go!!!! 7 completed 9 completed 5 completed 8 completed 2 completed 0 completed 6 completed 4 completed 1 completed 3 completed All runner passed the end pointspa