Concurrent.util工具之CountDownLatch & CyclicBarrier
CountDownLatch用法:
经常用于监控一些初始化操作,等初始化都完毕之后,通知主线程进行继续操作!!
CyclicBarrier
常用于多个线程都完成一定的准备工作之后,一起去执行操作。
例如: 你今天过生日,约定好,家人都到齐了,才能吃蛋糕,有一个人没到家,这个执行吃蛋糕的步骤就不能进行。
区别
CountDownLatch实例:
public class StudyConcurrentUtils {
public static void main(String[] args) {
/**
* 源码解释的非常清楚:只有countDown被调用2次,await方法才能通过
*
* the number of times {@link #countDown} must be invoked
* before threads can pass through {@link #await}
*/
final CountDownLatch countDownLatch = new CountDownLatch(2);
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("进入线程1...等待其他线程");
//线程阻塞
countDownLatch.await();
System.out.println("线程1继续开始执行其他工作");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"线程-1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("进入线程2...");
//模拟实际工作,休眠3秒
Thread.sleep(3000);
System.out.println("线程2任务完成...countDown一次通知线程1");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"线程-2");
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("进入线程3...");
//模拟实际工作,休眠3秒
Thread.sleep(3000);
System.out.println("线程3任务完成...countDown一次通知线程1");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"线程-3");
thread1.start();
thread2.start();
thread3.start();
}
}
CyclicBarrier事例:
/**
* @author zhanghuilong
* @version V1.0
* @desc
* @since 2018/01/11
*/
public class StudyConcurrentUtils1 {
//内部类
static class MyTask implements Runnable{
private CyclicBarrier cyclicBarrier;
private String taskNme;
public MyTask(CyclicBarrier cyclicBarrier, String taskNme) {
this.cyclicBarrier = cyclicBarrier;
this.taskNme = taskNme;
}
@Override
public void run() {
try {
//模拟任务处理前的数据准备
Thread.sleep(new Random().nextInt(3000));
System.out.println(taskNme+ "准备OK!");
cyclicBarrier.await();
System.out.println(taskNme+"开始执行任务!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
//主函数
public static void main(String[] args) {
//约定好3个准备好以后,才开始await()之后的操作
CyclicBarrier cyclicBarrier = new CyclicBarrier(3);//修改成4
//初始化容量为3个线程的线程池
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.submit(new MyTask(cyclicBarrier, "任务1"));
executorService.submit(new MyTask(cyclicBarrier, "任务2"));
executorService.submit(new MyTask(cyclicBarrier, "任务3"));
executorService.shutdown();
}
}
打印result:
如果把约定的线程数改为4个,那么你会发现任务准备好之后不会去执行await之后的代码,一直等待阻塞着: