看完后,你再也不用怕面试问并发编程啦(13)


看完后,你再也不用怕面试问并发编程啦

文章插图
CyclicBarrier类说明CyclicBarrier(int parties)创建对象,参数表示屏障拦截的线程数量,初始化相互等待的线程数量int await()告诉CyclicBarrier自己已经到达了屏障 , 然后当前线程被阻塞返回值int为达到屏障器的索引: 索引未达到屏障线程数量-1,0表示最后一个达到屏障int getParties()获取 CyclicBarrier 打开屏障的线程数量void reset()使CyclicBarrier回归初始状态 , 它做了两件事 。如果有正在等待的线程,则会抛出 BrokenBarrierException 异常,且这些线程停止等待,继续执行 。将是否破损标志位broken置为 false 。boolean isBroken()获取是否破损标志位broken的值,此值有以下几种情况 。1.CyclicBarrier初始化时,broken=false表示屏障未破损 。2.如果正在等待的线程被中断,则broken=true,表示屏障破损 。3.如果正在等待的线程超时 ,  则broken=true,表示屏障破损 。4.如果有线程调用 CyclicBarrier.reset() 方法,则broken=false,表示屏障回到未破损状态 。int getNumberWaiting()获取达到屏障阻塞等待的线程数CyclicBarrier(int parties,Runnable barrierAction)用于所有线程到达屏障时,优先执行barrierAction的线程 代码:package cn.itcast.thread;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.TimeUnit;public class Test17 {// 定义同步屏障对象private static CyclicBarrier cb = new CyclicBarrier(2);public static void main(String[] args) {// 创建线程1new Thread(() -> {try {System.out.println("达到屏障阻塞线程数:" + cb.getNumberWaiting());cb.await(); // 达到屏障阻塞,+1System.out.println("运行结束1"); // 不会运行} catch (Exception e) {e.printStackTrace();}}).start();// 创建线程2new Thread(() -> {try {System.out.println("达到屏障阻塞线程数:" + cb.getNumberWaiting());cb.await(); // 达到屏障阻塞,+1System.out.println("运行结束2"); // 不会运行} catch (Exception e) {e.printStackTrace();}}).start();try {TimeUnit.SECONDS.sleep(2);// 会运行,没有到达屏障,不会阻塞System.out.println("主线程完成,拦截线程数:" + cb.getParties()+ " , 达到屏障阻塞线程数:" + cb.getNumberWaiting());} catch (InterruptedException e) {e.printStackTrace();}}} 运行效果
由于两个子线程的调度是由CPU决定的,两个子线程都有可能先执行,所以会产生两种输出:
看完后,你再也不用怕面试问并发编程啦

文章插图
说明:由于所有线程都达到屏障,所有阻塞线程被释放,所以阻塞线程为0
如果把new CyclicBarrier(2)修改成new CyclicBarrier(3),则主线程和子线程会永远等待 , 因为没有第三个线程执行await方法,即没有第三个线程到达屏障,所以之前到达屏障的两个线程都不会继续执行 。private static CyclicBarrier cb = new CyclicBarrier(3); 
看完后,你再也不用怕面试问并发编程啦

文章插图
19、并发工具类:Semaphore(信号量)目标:掌握Semaphore的使用
介绍
Semaphore(信号量)限制着访问某些资源的线程数量,在到达限制的线程数量之前,线程能够继续进行资源的访问 , 一旦访问资源的数量到达限制的线程数量 , 这个时候线程就不能够再去获取资源,只有等待有线程退出资源的获取 。
应用场景
比如模拟一个停车场停车信号,假设停车场只有两个车位 , 一开始两个车位都是空的 。这时同时来了两辆车,看门人允许它们进入停车?。?然后放下车拦 。以后来的车必须在入口等待,直到停车场中有车辆离开 。这时,如果有一辆车离开停车?。?看门人得知后,打开车拦,放入一辆,如果又离开一辆,则又可以放入一辆,如此往复 。
看完后,你再也不用怕面试问并发编程啦

文章插图
API方法
信号量维护了一个许可集 。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可 。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者让其运行 。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动 。
所以一个Semaphore 信号量有且仅有 3 种操作,且它们全部是原子的 。