CyclicBarrier
允许一组线程全部等待彼此达到共同屏障点的同步辅助
CyclicBarrier也是一个计数器,只不过它是 加数器 CountDownLatch是减数器
代码测试:集齐7个龙珠召唤神龙
package com.wyh.JUCUtil; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; /** * @program: JUC * @description: * @author: 魏一鹤 * @createDate: 2022-02-18 22:28 **/ //CyclicBarrier屏蔽 本质就是一个增数器 //集齐七颗龙珠召唤神龙 public class CyclicBarrierDemo { public static void main(String[] args){ //创建CyclicBarrier //需要两个参数 它有两个参数 1 计数大小 2 runnable线程 这里直接用lambda表达式 CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{ //计数器到7才会召唤神龙 System.out.println("召唤神龙成功"); }); //创建7个线程 for (int i = 1; i <= 7; i++) { //lambda表达式能操作到循环变量i吗 答案是不能的 //想要再lambda表达式使用循环变量i 需要定义final常量 然后再lambda表达式使用常量 final int temp=i; new Thread(()->{ System.out.println(Thread.currentThread().getName() + "收集了"+temp+"颗龙珠"); try { //等待计数器执行完了 也就是变成7 需要抛异常 cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }).start(); } } }
Thread-0收集了1颗龙珠
Thread-4收集了5颗龙珠
Thread-5收集了6颗龙珠
Thread-3收集了4颗龙珠
Thread-2收集了3颗龙珠
Thread-1收集了2颗龙珠
Thread-6收集了7颗龙珠
召唤神龙成功
结果和我们想要的是一样的 但是如果我们把计数值换成8,但是只能集齐7会怎么样 程序会卡死在这,因为它永远也不能计数成8,await()方法只能等的就是计数完成之后执行,由于计数一直完不成就会一直等待
package com.wyh.JUCUtil; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; /** * @program: JUC * @description: * @author: 魏一鹤 * @createDate: 2022-02-18 22:28 **/ //CyclicBarrier屏蔽 本质就是一个增数器 //集齐七颗龙珠召唤神龙 public class CyclicBarrierDemo { public static void main(String[] args){ //创建CyclicBarrier //需要两个参数 它有两个参数 1 计数大小 2 runnable线程 这里直接用lambda表达式 CyclicBarrier cyclicBarrier = new CyclicBarrier(8,()->{ //计数器到7才会召唤神龙 System.out.println("召唤神龙成功"); }); //创建7个线程 for (int i = 1; i <= 7; i++) { //lambda表达式能操作到循环变量i吗 答案是不能的 //想要再lambda表达式使用循环变量i 需要定义final常量 然后再lambda表达式使用常量 final int temp=i; new Thread(()->{ System.out.println(Thread.currentThread().getName() + "收集了"+temp+"颗龙珠"); //等待计数器执行完了 也就是变成7 需要抛异常 try { cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }).start(); } } }
Thread-1收集了2颗龙珠
Thread-4收集了5颗龙珠
Thread-2收集了3颗龙珠
Thread-3收集了4颗龙珠
Thread-0收集了1颗龙珠
Thread-6收集了7颗龙珠
Thread-5收集了6颗龙珠
Semphore
Semphore:信号量 主要用作限流
//创建Semaphore 需要一个参数线程数量参数 停车位 3个
Semaphore semaphore = new Semaphore(3);
//得到
semaphore.acquire();
//释放
semaphore.release();
代码实现 抢车位 6个车 3个车位 123号车进去停车位456号车等待 1号车出去4好车进来
package com.wyh.JUCUtil; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; /** * @program: JUC * @description: Semaphore停车位测试 * @author: 魏一鹤 * @createDate: 2022-02-18 23:12 **/ //Semaphore限流 public class SemaphoreDemo { public static void main(String[] args) { //创建Semaphore 需要一个参数线程数量参数 停车位 3个 //它主要有两个方法 acquire()得到 release()释放 Semaphore semaphore = new Semaphore(3); //创建6个线程 6个车 for (int i = 1; i <= 6; i++) { new Thread(()->{ try { //得到 需要抛异常 semaphore.acquire(); //抢到车位 System.out.println(Thread.currentThread().getName() + "抢到了车位"); //休眠两秒 TimeUnit.SECONDS.sleep(2); System.out.println(Thread.currentThread().getName() + "离开了车位"); } catch (InterruptedException e) { e.printStackTrace(); }finally { //释放 semaphore.release(); } },String.valueOf(i)).start(); } } }
1抢到了车位
3抢到了车位
2抢到了车位
1离开了车位
3离开了车位
2离开了车位
5抢到了车位
4抢到了车位
6抢到了车位
5离开了车位
6离开了车位
4离开了车位
原理
主要是Semaphore 的两个方法
acquire()得到 假设如果已经满了,等待被释放为止
release()释放 释放,会将当前的释放量+1,然后唤醒等待线程
作用
1 多个共享资源互斥的使用
2 并发限流 控制最大的线程数 保证服务器的安全和高可用