JUC CyclicBarrier和Semphore

简介: JUC CyclicBarrier和Semphore

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 并发限流  控制最大的线程数 保证服务器的安全和高可用

目录
相关文章
|
C语言
C语言模块化程序设计
C语言模块化程序设计
229 0
|
机器学习/深度学习 人工智能 自然语言处理
从此告别PPT制作的烦恼:ChatGPT和MindShow帮你快速完成
从此告别PPT制作的烦恼:ChatGPT和MindShow帮你快速完成
|
12月前
|
存储 Python
CSV文件
【10月更文挑战第18天】CSV文件
811 2
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
11月前
|
数据采集 缓存 程序员
python协程使用教程
1. **协程**:介绍了协程的概念、与子程序的区别、优缺点,以及如何在 Python 中使用协程。 2. **同步与异步**:解释了同步与异步的概念,通过示例代码展示了同步和异步处理的区别和应用场景。 3. **asyncio 模块**:详细介绍了 asyncio 模块的概述、基本使用、多任务处理、Task 概念及用法、协程嵌套与返回值等。 4. **aiohttp 与 aiofiles**:讲解了 aiohttp 模块的安装与使用,包括客户端和服务器端的简单实例、URL 参数传递、响应内容读取、自定义请求等。同时介绍了 aiofiles 模块的安装与使用,包括文件读写和异步迭代
318 0
|
SQL 关系型数据库 API
Python 开发环境的准备以及一些常用类库模块的安装
在学习和开发Python的时候,第一步的工作就是先准备好开发环境,包括相关常用的插件,以及一些辅助工具,这样我们在后续的开发工作中,才能做到事半功倍。下面介绍一些Python 开发环境的准备以及一些常用类库模块的安装和使用的经验总结,供大家参考了解。
|
11月前
|
机器学习/深度学习 自然语言处理 算法
深入理解机器学习算法:从线性回归到神经网络
深入理解机器学习算法:从线性回归到神经网络
|
SQL JSON 关系型数据库
JSON_TABLE 两全其美
在这篇博客文章中,我将向您展示如何做到这一点,并讨论JSON_TABLE如何启用使用SQL处理JSON数据的新方法。
8321 0
|
机器学习/深度学习 自然语言处理 安全
【开源威胁情报挖掘3】开源威胁情报融合评价
【开源威胁情报挖掘3】开源威胁情报融合评价
343 0
|
Java API Android开发
2022最新android设备uuid、udid使用教程​
2022最新android设备uuid、udid使用教程​
1300 0