CyclicBarrier和CountDownLatch笔记
一、CyclicBarrier的使用
Barrier是栅栏,障碍物的意思,这里将它理解为栅栏。
Cyclic是重复利用的意思。
CyclicBarrier:可重复利用的栅栏。这里附上官方文档的一句解释:The barrier is called<em>cyclic</em> because it can be re-used after the waiting threads are released.
大概意思是等待的线程被释放以后就可以重新使用这个栅栏。
栅栏的使用条件:它必须使用在线程类中。也就是说你可以把CyclicBarrier作为线程类的一个变量。
在代码中插入一个栅栏,当代码执行到栅栏处就被拦截住了,不能继续往下执行。一直等到所有的线程都执行到栅栏处,才可以继续执行。
public static void main(String[] args) { CyclicBarrier barrier = new CyclicBarrier(10);//设置你要拦截的线程的个数。 for(int i = 0; i < 10; i++) { new Thread(new Worker(barrier)).start(); System.out.println("第" + i + "个线程已经启动"); } }
线程类中持有CyclicBarrier的引用。
class Worker implements Runnable { private CyclicBarrier barrier; public Worker(CyclicBarrier barrier) { this.barrier = barrier; } @Override public void run() { try { Thread.sleep((long)(Math.random() * 10000)); } catch (InterruptedException e) { e.printStackTrace(); } try { System.out.println("代码...."); barrier.await();//栅栏,栅栏的启用就是调用await()方法就行了。还可以调用它的重载方法await(long timeout, TimeUnit unit) System.out.println("代码....."); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println("你好"); } }
二、CountDownLatch
感觉CountDownLatch和CyclicBarrier有点相似,所以就记在一起。
说一下两者的区别,CyclicBarrier的作用是让多个线程都执行到栅栏的时候,这写线程再继续执行,比如,有十个线程,要全部等到这十个线程都到栅栏以后,再各自前进。而CountDownLatch则是用来让多个线程都执行完以后再继续往下执行。比如,在一个主线程中创建了10个线程并启动运行它们。本来的是这十个线程启动完后主线程就可以继续往下执行了,但是现在需要等这十个线程执行完毕以后(更准确的说应该是getCount()的返回值为0的时候)主线程才能往下执行。那么这时候就需要CountDownLatch来完成。
例子:
public class CountDownLatchTest { public static void main(String[] args) { CountDownLatch countDownLatch = new CountDownLatch(5); for(int i = 0; i < 10; i++) { new Thread(new CountDownRun(countDownLatch, i)).start(); } //需要等到10个线程都执行完以后才能继续往下执行。准确的来说应该是计数器不断减一,当减到0的时候主线程就可以继续往下执行了。 try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("await()之后继续执行"); } }
class CountDownRun implements Runnable { private CountDownLatch countDownLatch;//线程持有同一个countDownLatch private int i; public CountDownRun(CountDownLatch countDownLatch, int i) { this.countDownLatch = countDownLatch; this.i = i; } @Override public void run() { System.out.println("你好!" + i); try { Thread.sleep((long)(Math.random() * 1000)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("睡醒了。。。" + i); countDownLatch.countDown();//减一 System.out.println("减一后"); } }
三、CountDownLatch还有一种用法,参见类注释。