两个看上去有点像的类,都在java.util.concurrent下,都可以用来表示代码运行到某个点上,二者的区别在于:
(1)CyclicBarrier的某个线程运行到某个点上之后,该线程即停止运行,直到所有的线程都到达了这个点,所有线程才重新运行;CountDownLatch则不是,某线程运行到某个点上之后,只是给某个数值-1而已,该线程继续运行
(2)CyclicBarrier只能唤起一个任务,CountDownLatch可以唤起多个任务
(3)CyclicBarrier可重用,CountDownLatch不可重用,计数值为0该CountDownLatch就不可再用了
CyclicBarrier
public class CyclicBarrierTest {
/**
* 工作线程
*/
private static class Work implements Runnable{
private CyclicBarrier cyclicBarrier ;
public Work(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
//只有所有人都完成第一阶段才能开始第二阶段
public void run() {
firstwork();
try {
//等待完成第一阶段工作
cyclicBarrier.await();
secondWork();
//完成第二阶段工作
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
//work1
private void firstwork(){
System.out.println(Thread.currentThread().getName()+"完成第一项工作");
}
//work2
private void secondWork(){
System.out.println(Thread.currentThread().getName()+"完成第二阶段");
}
};
//通知线程
private static class NoticeThread implements Runnable{
boolean [] flag = new boolean[2] ;
public void run() {
if (!flag[0]){
System.out.println("通知:第一阶段完成");
flag[0] = true;
}else
if( !flag[1]){
System.out.println("通知:第二阶段完成");
}
}
}
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(10,new NoticeThread());
for (int i =0 ;i<10 ;i++){
new Thread(new Work(cyclicBarrier)).start();
}
}
}
结果
Thread-0完成第一项工作
Thread-2完成第一项工作
Thread-1完成第一项工作
Thread-4完成第一项工作
Thread-3完成第一项工作
Thread-7完成第一项工作
Thread-8完成第一项工作
Thread-6完成第一项工作
Thread-5完成第一项工作
Thread-9完成第一项工作
通知:第一阶段完成
Thread-9完成第二阶段
Thread-0完成第二阶段
Thread-2完成第二阶段
Thread-1完成第二阶段
Thread-4完成第二阶段
Thread-3完成第二阶段
Thread-7完成第二阶段
Thread-8完成第二阶段
Thread-6完成第二阶段
Thread-5完成第二阶段
通知:第二阶段完成
从结果看到 cyclicBarrier 阻塞所有线程, 之后 都到达后 ,会唤醒一个通知线程, 之后所有阻塞的工作线程继续执行, 都到达第二阶段 之后唤醒 通知线程,再继续. 并且一个 cyclicBarrier可以重复利用.
CountDownLunch
public class CountDownLunchTest {
private CountDownLatch countDownLatch = new CountDownLatch(5);
public void doWork(){
countDownLatch.countDown();
System.out.println(countDownLatch.getCount());
}
public static void main(String[] args) throws InterruptedException {
final CountDownLunchTest test = new CountDownLunchTest();
Runnable runnable = new Runnable() {
public void run() {
test.doWork();
}
};
for (int i = 0; i <5; i++) {
new Thread(runnable).start();
}
test.countDownLatch.await();
System.out.println("end");
}
}
其他参考:https://github.com/wowdouble/wowdouble/tree/master/threaddemo