CountDownLatch与CyclicBarrier使用
介绍
CountDownLatch 倒计时器锁 CyclicBarrier 线程-同步装置之
控制并发流程的工具类,作用就是帮助我们程序员更容易得让线程之间合作
让线程之间相互配合,来满足业务逻辑
比如让线程A等待线程B执行完毕后再执行等合作策略简简单单的翻译肯定不能让你满意,
CountDownLatch特点
让所有线程处于等待转态,当计数器减少countDown()时将自动放闸,
CountDownLatch使用(代码演示)
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 描述: 工厂中,质检,5个工人检查,所有人都认为通过,才通过
*/
public class CountDownLatchDemo1 {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(5);
ExecutorService service = Executors.newFixedThreadPool(5);//创建普通线程池
for (int i = 0; i < 5; i++) {
final int no = i + 1;
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep((long) (Math.random() * 10000));//随机休眠一段时间
System.out.println("No." + no + "完成了检查。");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown();//减少信号量
}
}
};
service.submit(runnable);
}
System.out.println("等待5个人检查完.....");
latch.await();//等待latch 中的子线程全面部完成
System.out.println("所有人都完成了工作,进入下一个环节。");
}
}
运行结果:
等待5个人检查完.....
No.3完成了检查。
No.2完成了检查。
No.5完成了检查。
No.1完成了检查。
No.4完成了检查。
所有人都完成了工作,进入下一个环节。
主要方法
- await()
- 使当前线程等待直到锁向下计数为零,除非线程 interrupted。
- await(long timeout, TimeUnit unit)
- 使当前线程等待直到锁向下计数为零,除非线程 interrupted,或指定的等待时间的流逝。
- countDown()
- 减少锁的数量,释放所有等待的线程,如果计数为零。
- getCount() – 返回当前计时器
适用场景
- 一个线程等待多个线程都执行完毕,再继续自己的工作。
- 多个线程等待某一个线程的信号 ,同时开始执行。
CyclicBarrier特点
CountDownLatch和CyclicBarrier 使用区别并不大
最大区别在于:CyclicBarrier 的线程操作方法时可以重复使用的,而CountDownLatch却不行。
CyclicBarrier支持自定义Thread 进行回调
CyclicBarrier使用 (代码演示)
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* 描述: 演示CyclicBarrier
*/
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
System.out.println("所有人都到场了, 大家统一出发!");
}
});
for (int i = 0; i < 10; i++) {
new Thread(new Task(i, cyclicBarrier)).start();
}
}
static class Task implements Runnable{
private int id;
private CyclicBarrier cyclicBarrier;
public Task(int id, CyclicBarrier cyclicBarrier) {
this.id = id;
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
System.out.println("线程" + id + "现在前往集合地点");
try {
Thread.sleep((long) (Math.random()*10000));
System.out.println("线程"+id+"到了集合地点,开始等待其他人到达");
cyclicBarrier.await();
System.out.println("线程"+id+"出发了");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
主要方法
- await()
- 等到所有的 parties援引 await这个屏障
- reset()
- 重置为其初始状态的屏障。
使用场景
- 线程之间合作与调度
- 一些大流并发的测试
总结
- CountDownLatch会阻塞主线程,CyclicBarrier不会阻塞主线程,只会阻塞子线程。
- CountDownLatch使用场景主要是事件之间的协调
- CyclicBarrier而则不需要,主要用于大流量时的线程之间的协调
- CyclicBarrier 支持Thread 的处理回调 而 CountDownLatch不支持
注意
协调指是线程之间的上下文切换之间的协调,CountDownLatch针对的是事件之间的协调(即 统一开始,统一结束)
可重用性不同
CountDownLatch不可重复使用调度完成后是不允许重置,如他的名字般计时器,而CyclicBarrier不同允许重置reset()–重置为新的内存屏障。