一:CyclicBarrier
?? CyclicBarrier可以理解为屏障,通过它可以实现让一组线程等待至某个状态之后再全部同时执行。更重要的是,当所有等待线程都被释放以后,CyclicBarrier可以被重用。
?1.1: CyclicBarrier的构造方法如下:
?? public CyclicBarrier(int parties):参数parties指让多少个线程或者任务等待至barrier状态。
?? public CyclicBarrier(int parties, Runnable barrierAction):表示当等待的线程都到达了barrier状态后,优先执行barrierAction。
?1.2: CyclicBarrier的主要方法
?? int await():让所有线程都等待,直到全部到达barrier为止。
?? int await(long timeout, TimeUnit unit):让所有线程都等待,如果在指定的超时时间内,还有线程未到底,则让已经处于barrier的所有线程执行。
?? boolean isBroken():用来判断阻塞的线程是否被中断。
?? void reset():重置barrier。
?? int getNumberWaiting():获取阻塞的线程数量。
二:举例说明
?2.1:示例代码如下
?barrier对象设置计数器为4,当4个线程都到底barrier时,然后共同执行.
?public class JdkCyclicBarrier {
??? static CyclicBarrier barrier = new CyclicBarrier(4);
??? public static void main(String[] args) throws InterruptedException {
??? ??? ExecutorService service = Executors.newFixedThreadPool(4);
??? ??? for (int i = 1; i <= 4; i++) {
??? ??? ??? Callable<Void> task = new Callable<Void>() {
??? ??? ??? ??? @Override
??? ??? ??? ??? public Void call() {
??? ??? ??? ??? ??? try {
??? ??? ??? ??? ??? ??? System.out.println("线程:" + Thread.currentThread().getName()
??? ??? ??? ??? ??? ??? ??? ??? + "到了");
??? ??? ??? ??? ??? ??? if (barrier.getNumberWaiting() == 3) {
??? ??? ??? ??? ??? ??? ??? System.out.println("4个人都到齐了,可以开始打麻将了");
??? ??? ??? ??? ??? ??? }
??? ??? ??? ??? ??? ??? barrier.await();
??? ??? ??? ??? ??? } catch (InterruptedException | BrokenBarrierException e) {
??? ??? ??? ??? ??? ??? e.printStackTrace();
??? ??? ??? ??? ??? }
??? ??? ??? ??? ??? return null;
??? ??? ??? ??? }
??? ??? ??? };
??? ??? ??? service.submit(task);
??? ??? }
??? ??? service.shutdown();
??? }
}
可能得运行结果如下:
? 线程:pool-1-thread-1到了
? 线程:pool-1-thread-4到了
? 线程:pool-1-thread-3到了
? 线程:pool-1-thread-2到了
? 4个人都到齐了,可以开始打麻将了
可以看到,当4个线程都到达barrier后,所以线程被释放,然后同时执行。
2.2:CyclicBarrier和CountDownLatch的区别
?二者之间的主要区别是,coutDownLatch在计算完后,不能被重用,,cyclicBarrier是可以的。
? 看下面的例子:
? public class CyclicBarrierExample2 {
??? public static void main(String[] args) throws InterruptedException {
??? ??? CyclicBarrier barrier = new CyclicBarrier(2);
??? ??? CountDownLatch latch = new CountDownLatch(2);
??? ??? for (int i = 0; i < 2; i++) {
??? ??? ??? new ReadData(barrier,latch).start();
??? ??? }
??? ??? latch.await();
??? ??? System.out.println("barrier被重用");
??? ??? for (int j = 0; j< 2; j++) {
??? ??? ??? new ReadData(barrier).start();
??? ??? }
??? }
??? static class ReadData extends Thread {
??? ??? private CyclicBarrier barrier;
??? ???
??? ??? private CountDownLatch latch;
??? ???
??? ??? public ReadData(CyclicBarrier barrier) {
??? ??? ??? this.barrier = barrier;
??? ??? }
??? ??? public ReadData(CyclicBarrier barrier,CountDownLatch latch) {
??? ??? ??? this.barrier = barrier;
??? ??? ??? this.latch = latch;
??? ??? }
??? ??? @Override
??? ??? public void run() {
??? ??? ??? System.out.println("线程:" + Thread.currentThread().getName() + "开始执行");
??? ??? ??? try {
??? ??? ??? ??? Thread.sleep(2000);
??? ??? ??? ??? System.out.println("线程:" + Thread.currentThread().getName() + "运行完毕!");
??? ??? ??? ??? barrier.await();
??? ??? ??? ??? if(null != latch){
??? ??? ??? ??? ??? latch.countDown();
??? ??? ??? ??? }
??? ??? ??? } catch (InterruptedException e) {
??? ??? ??? ??? e.printStackTrace();
??? ??? ??? } catch (BrokenBarrierException e) {
??? ??? ??? ??? e.printStackTrace();
??? ??? ??? }
??? ??? ??? System.out.println(Thread.currentThread().getName() + "所有线程运行完毕,放行");
??? ??? }
??? }
}
可能得运行结果如下:
线程:Thread-0开始执行
线程:Thread-1开始执行
线程:Thread-0运行完毕!
线程:Thread-1运行完毕!
Thread-1所有线程运行完毕,放行
Thread-0所有线程运行完毕,放行
barrier被重用
线程:Thread-2开始执行
线程:Thread-3开始执行
线程:Thread-3运行完毕!
线程:Thread-2运行完毕!
Thread-2所有线程运行完毕,放行
Thread-3所有线程运行完毕,放行
可以看到,barrier实现了重用。
原文:http://314317681.iteye.com/blog/2287426