转自:http://www.liubey.org/countdownlatch_vs_cyclicbarrier/java
概述
app
CountDownLatch : 一个线程(或者多个), 等待另外N个线程完成某个事情以后才能执行。ide
CyclicBarrier : N个线程相互等待,任何一个线程完成以前,全部的线程都必须等待。测试
Semaphore:能够控制某个资源可被同时访问的个数,经过 acquire() 获取一个许可,若是没有就等待,而 release() 释放一个许可。ui
举例this
体育课时老师拿着秒表测试同窗的800米成绩,那需求就是很简单了,老师在起跑处组织你们一块儿跑的瞬间按下秒表计时开始,而后再终点处等待最后一个学生经过终点后开始聚集学生成绩。pwa
1)await(),阻塞等待,直到计数器清零
2)await(int timeout, TimeUnit unit),使线程阻塞,除非被中断或者超过等待的最大时间
若是达到计数器清零,则await返回true,若是等待超过了最大的等待时间,则返回false
3)countDown(),计数器减一,当计数器清零时,await的线程被唤醒,线程继续执行
4)getCount (),获取当前计数器的大小线程
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;调试
public class TeacherWithStopwatch {
public static final int NUMBER_OF_STUDENT = 10;
public static final int NUMBER_OF_TEACHER = 1;
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
CountDownLatch studentSignal = new CountDownLatch(NUMBER_OF_STUDENT);
CountDownLatch teacherSignal = new CountDownLatch(NUMBER_OF_TEACHER);
for (int i = 0; i < NUMBER_OF_STUDENT; i++) {
executor.execute(new Student(i, studentSignal, teacherSignal));
}
try {
System.out.println("各就各位!开跑!");
teacherSignal.countDown();
studentSignal.await();
System.out.println("结果发送到汇报成绩的系统");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
}
}游戏
import java.util.concurrent.CountDownLatch;
public class Student implements Runnable {
private int id;
private CountDownLatch studentSignal;
private CountDownLatch teacherSignal;
public Student(int id, CountDownLatch studentSignal,
CountDownLatch teacherSignal) {
this.id = id;
this.studentSignal = studentSignal;
this.teacherSignal = teacherSignal;
}
@Override
public void run() {
try {
teacherSignal.await();
System.out.println("学生" + id + "起跑...");
System.out.println("学生" + id + "到达终点。");
studentSignal.countDown();
System.out.println("学生" + id + "继续干其余事情");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
有四个游戏玩家玩游戏,游戏有三个关卡,每一个关卡必需要全部玩家都到达后才能容许通关。
其实这个场景里的玩家中若是有玩家A先到了关卡1,他必须等待其余全部玩家都到达关卡1时才能经过。
也就是说线程之间须要互相等待,这和CountDownLatch的应用场景有区别,
CountDownLatch里的线程是到了运行的目标后继续干本身的其余事情,而这里的线程须要等待其余线程后才能继续完成下面的工做。
public CyclicBarrier(int parties) 建立一个新的 CyclicBarrier,
它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在启动 barrier 时执行预约义的操做。
public CyclicBarrier(int parties, Runnable barrierAction) 建立一个新的 CyclicBarrier,
它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操做,
该操做由最后一个进入 barrier 的线程执行。
public int await() throws InterruptedException, BrokenBarrierException 在全部参与者都已经在此 barrier 上调用 await 方法以前,将一直等待。
public int await(long timeout,TimeUnit unit) throws InterruptedException, BrokenBarrierException,TimeoutException
在全部参与者都已经在此屏障上调用 await 方法以前将一直等待,或者超出了指定的等待时间。
public int getNumberWaiting() 返回当前在屏障处等待的参与者数目。此方法主要用于调试和断言。
public int getParties() 返回要求启动此 barrier 的参与者数目。
public boolean isBroken() 查询此屏障是否处于损坏状态。
public void reset() 将屏障重置为其初始状态。
public class GameBarrier {
public static final int NUMBER_OF_PLAYERS = 4;
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(NUMBER_OF_PLAYERS);
CyclicBarrier barrier = new CyclicBarrier(NUMBER_OF_PLAYERS, new Runnable() {
@Override
public void run() {
System.out.println("全部玩家经过第一关!");
}
});
for (int i = 0; i < NUMBER_OF_PLAYERS; i++) {
executor.execute(new Player(i, barrier));
}
executor.shutdown();
}
}
public class Player implements Runnable {
private CyclicBarrier cyclicBarrier;
private int id;
public Player(int id, CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
this.id = id;
}
@Override
public void run() {
try {
System.out.println("玩家" + id + "经过第一关...");
cyclicBarrier.await();
System.out.println("玩家" + id + "进入第二关...");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
一个资源池只能同时五我的使用,那么十我的来轮询使用的状况就是每一个人都先申请资源,使用完归还于下一我的使用。
构造器中的fairness为true时,Semaphore保证各线程之后进先出(FIFO)的方式得到信号量。若是fairness为false,则不保证这种顺序,容许各线程之间的“讨价还价”。
tryAcquire与release为主要方法
public class Person implements Runnable { private SemaphorePool pool; private int id; public Person(int id, SemaphorePool pool) { this.pool = pool; this.id = id; } @Override public void run() { try { pool.applyResource(); System.out.println("人物" + id + "进入"); Thread.sleep(1000); System.out.println("人物" + id + "离开"); } catch (InterruptedException e) { e.printStackTrace(); } finally { pool.releaseResource(); } }}public class SemaphorePool { private Semaphore canExecuteCount = new Semaphore(5, true); private static final int TRY_EXECUTE_TIMEOUT = 20; public boolean applyResource() { boolean canExecute = false; try { canExecute = canExecuteCount.tryAcquire(1, TRY_EXECUTE_TIMEOUT, TimeUnit.SECONDS); } catch (InterruptedException e) {} return canExecute; } public void releaseResource() { canExecuteCount.release(1); }}public class TestSemaphore { public static final int NUMBER_OF_PERSONS = 10; public static final SemaphorePool pool = new SemaphorePool(); public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(NUMBER_OF_PERSONS); for(int i=0;i<NUMBER_OF_PERSONS;i++) { executor.execute(new Person(i, pool)); } executor.shutdown(); }}