如上图所示,当7个线程都完成latch.countDown调用后,最下面那条线程会从latch.await返回,继续执行后面的代码html
咱们来看一个具体的例子。假设咱们使用一台多核的机器对一组数据进行排序,那么咱们能够把这组数据分到不一样线程中进行排序,而后合并;能够利用线程池来管理多线程;能够将CountDownLatch用做各个分组数据都排好序的通知。下面是代码片断:java
先看主线程编程
int count = 10; final CountDownLatch latch = new CountDownLatch(count); int[] datas = new int[10204]; int step = datas.length / count; for (int i=0; i < count; i++) { int start = i * step; int end = (i+1) * step; if (i == count - 1) end = datas.length; threadpool.execute(new MyRunnable(latch, datas, start, end)); } latch.await(); //合并数据
咱们再看一下具体任务的代码,即MyRunnable的run方法的实现:多线程
public void run() { //数据排序 latch.countDown(); }
|
CountDownLatch
|
CyclicBarrier
|
适用场景
|
主线程等待其余工做线程结束
|
多个线程相互等待,直到全部线程都达到一个障碍点Barrier
|
主要方法
|
CountDownLatch(int count) 主线程调用:初始化计数
await() 主线程调用 : 阻塞,直到等待计数为0时解除阻塞
countDown() 工做线程调用 : 计数减1
|
CyclicBarrier(int parties , Runnnable barrierAction) : 初始化参与者数量和障碍点执行Action,action可选,由主线程初始化
await() : 由工做线程调用,每被调用一次,计数便会减小1,并阻塞住当前线程 , 直到全部线程都达到障碍点
|
等待结束
|
各线程之间再也不相互影响, 能够继续作本身的事情, 再也不执行下一个工做目标。
|
在障碍点到达后, 容许全部线程继续执行,到达下一个目标后,能够恢复使用CyclicBarrier, barrier 在释放等待线程后能够重用
|
异常
|
|
若是其中一个线程因为中断、错误、或者超时致使永久离开障碍点,其余线程也将抛出异常。
|
int count = 10; final CyclicBarrier barrier = new CyclicBarrier(count + 1); int[] datas = new int[10204]; int step = datas.length / count; for (int i=0; i < count; i++) { int start = i * step; int end = (i+1) * step; if (i == count - 1) end = datas.length; threadpool.execute(new MyRunnable(barrier, datas, start, end)); } barrier.await(); //合并数据
能够看到CyclicBarrier对象传入的参数值比CountDownLatch大1,缘由是构造CountDownLatch的参数是调用countDown的数量,而CyclicBarrier的数量是await的数量并发
public void run() { //数据排序 try { barrier.await(); }catch (...) }
public Semaphore(int permits) { //参数permits表示许可数目,即同时能够容许多少线程进行访问
sync = new NonfairSync(permits);
}
public Semaphore(int permits, boolean fair) { //这个多了一个参数fair表示是不是公平的,即等待时间越久的越先获取许可
sync = (fair)? new FairSync(permits) : new NonfairSync(permits);
}
semaphore.acquire(); try { //调用远程通讯的方法 } finally { semaphore.release(); }