1 前言
在JDK的并发包里提供了几个非常有用的并发工具类。CountDownLatch、CyclicBarrier和 Semaphore工具类提供了一种并发流程控制的手段,Exchanger工具类则提供了在线程间交换数 据的一种手段。本文会对这些并发工具类进行介绍。
2 等待多线程完成的CountDownLatch
2.1 CountDownLatch案例演示
countdownlatch 是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完毕再执行。从命名可以解读到 countdown 是倒数的意思,类似于我们倒计时的概念。
countdownlatch 提供了两个方法,一个是 countDown,一个是 await,countdownlatch 初始化的时候需要传入一个整数,在这个整数倒数到 0 之前,调用了 await 方法的程序都必须要等待,然后通过 countDown 来倒数。
public class CountDownLatchDemo { public static void main(String[] args) { CountDownLatch countDownLatch = new CountDownLatch(6); for (int i = 0; i < 6; i++) { new Thread(() -> { System.out.println(Thread.currentThread().getName()+"同学离开了"); countDownLatch.countDown(); }).start(); } try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"要关门了,此时教室已经没人了~"); } }
3 同步屏障CyclicBarrier
CyclicBarrier的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一 组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会 开门,所有被屏障拦截的线程才会继续运行。
3.1 CyclicBarrier使用场景
使用场景:5个工程师一起来公司应聘,招聘方式分为笔试和面试。首先,要等人到齐后,开始笔试;笔试结束之后,再一起参加面试。把5个人看作5个线程,代码如下:
Main类
public class Main { public static void main(String[] args) throws BrokenBarrierException, InterruptedException { CyclicBarrier barrier = new CyclicBarrier(5); for (int i = 0; i < 5; i++) { new MyThread("线程-" + (i + 1), barrier).start(); } } }
MyThread类:
public class MyThread extends Thread{ private final CyclicBarrier barrier; private final Random random = new Random(); public MyThread(String name, CyclicBarrier barrier) { super(name); this.barrier = barrier; } @Override public void run() { try { Thread.sleep(random.nextInt(2000)); System.out.println(Thread.currentThread().getName() + " - 已经到达公司"); barrier.await(); Thread.sleep(random.nextInt(2000)); System.out.println(Thread.currentThread().getName() + " - 已经笔试结束"); barrier.await(); Thread.sleep(random.nextInt(2000)); System.out.println(Thread.currentThread().getName() + " - 已经面试结束"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } super.run(); } }
在整个过程中,有2个同步点:第1个同步点,要等所有应聘者都到达公司,再一起开始笔试;第2个同步点,要等所有应聘者都结束笔试,之后一起进入面试环节。
3.3 CyclicBarrier与CountDownLatch 区别
CountDownLatch 是一次性的,CyclicBarrier 是可循环利用的
CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()方法重置,可以使用多次,所以CyclicBarrier能够处理更为复杂的场景;
4 控制并发线程数的Semaphore
Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以 保证合理的使用公共资源
4.1 Semaphore的使用场景
public class SemaphoreDemo { public static void main(String[] args) { Semaphore semaphore=new Semaphore(3);//此时海底捞有3个空桌 for (int i = 0; i < 6; i++) { new Thread(() -> { try { semaphore.acquire(); System.out.println("第"+Thread.currentThread().getName()+"等待者抢到座位。"); //假设每桌客人吃饭时间为3S TimeUnit.SECONDS.sleep(3); System.out.println("第"+Thread.currentThread().getName()+"客人吃完饭离开。"); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } },String.valueOf(i)).start(); } } }
作者:干天慈雨
链接:https://www.jianshu.com/p/6251c13bbb2e
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。