JUC Lock 计数锁

news2024/11/18 1:34:30

文章目录

  • Semaphore
    • 继承关系图
    • 构造函数
    • 常用 API
    • 示例
    • 总结
  • CountDownLatch
    • 继承关系图
    • 构造函数
    • 常用 API
    • 示例
  • CyclicBarrier
    • 原理
    • 构造方法
    • 常用 API
    • 示例

Semaphore

Semaphore字面意思是信号量。主要用于控制有限的资源的访问数量。比如:公共厕所有5个蹲位,但有10个人要上厕所、仓库容量有限,达到容量后无法再存储货物,除非有出货。再比如我们的池技术(连接池、对象池等),池的大小有限,但使用者很多,我们需要不断的进行获取连接和释放连接。

继承关系图

在这里插入图片描述

Semaphore 内部同样有个静态内部类 Sync,同样实现了 AQS,同样有公平(FairSync)和非公平两个实现 (NonfairSync)

构造函数

/**
  *
  * @param permits 资源数量
  * 按蹲位的示例来说,者就是蹲位的数量,默认使用非公平策略
  */
public Semaphore(int permits) {
    sync = new NonfairSync(permits);
}

public Semaphore(int permits, boolean fair) {
    sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}

常用 API

  • acquire 系列
/**
  *
  * 获取一个资源
  * 当资源已经不够时,当前申请的线程会阻塞
  * 此方式线程可以被打断,被打断后抛出 InterruptedException 
  */
public void acquire() throws InterruptedException 

/**
  *
  * 获取 permits 个资源
  * 当资源已经不够时,当前申请的线程会阻塞
  * 此方式线程可以被打断,被打断后抛出 InterruptedException 
  */
public void acquire(int permits) throws InterruptedException

/**
  *
  * 获取一个资源
  * 当资源已经不够时,当前申请的线程会阻塞
  * 此方式线程就算被打断,它依然会等待获取资源,只是获取资源的时间和不打断获取资源的时间有所变化 
  */
public void acquireUninterruptibly()
public void acquireUninterruptibly(int permits)
  • tryAcquire 系列
/**
  *
  * 立即获取一个资源
  * 当资源足够时,立即返回 true
  * 当资源已经不够时,立即返回 false
  */
public boolean tryAcquire()
/**
  *
  * 立即获取一个资源
  * 当资源足够时,立即返回 true
  * 当资源已经不够时,等待对应到时间,还没有资源才会立即返回 false
  */
public boolean tryAcquire(long timeout, TimeUnit unit)
        throws InterruptedException
public boolean tryAcquire(int permits)
public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
        throws InterruptedException
  • release 释放资源
/**
  *
  * 释放出一个资源
  */
public void release()
/**
  *
  * 释放出 permits 个资源
  */
public void release(int permits)
  • 其他
/**
  * 获取当前可用资源个数
  */
public int availablePermits()
/**
  * 获取所有可用资源个数
  */
public int drainPermits()

/**
  * 是否是公平锁
  */	
public boolean isFair()

/**
  * 是否有线程正在等待获取资源
  */	
public final boolean hasQueuedThreads()

/**
  * 正在等待获取资源的线程数量
  */
 public final int getQueueLength() 

示例

比如公共厕所一共有5个蹲位,当前有10个人来上厕所

import lombok.extern.slf4j.Slf4j;

import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

@Slf4j
public class SemaphoreTest {

    public static void main(String[] args) {

        // 公共厕所 5 个蹲位
        Semaphore toilet = new Semaphore(5);

        // 10 个人上厕所
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                log.debug("想上厕所");
                if(toilet.availablePermits() == 0){
                    log.debug("没位置,等一下");
                }
                
                try{
                    toilet.acquire();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                log.debug("抢到位置了....");
                try {
                    // 模拟上厕所时间
                    TimeUnit.MILLISECONDS.sleep(new Random().nextInt(1000));
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                log.debug("上完了");
                toilet.release();

            },"第"+i+"个人").start();
        }

    }

}

总结

Semaphore 在实际应用中其实使用得并不多,因为当资源较少的时候,可能造成大量线程阻塞。而且我们使用线程池的方式也可以达到这些效果,而且线程池的使用更简单

CountDownLatch

倒数计数器。用于某个线程等待 CountDownLatch 的计数为 0 才开始执行。实际应用中的例子就是:某个线程的执行需要等待其他一个或多个并行线程执行完之后才能开始。

继承关系图

在这里插入图片描述

构造函数

/**
  * 
  * @Param count 其实数值
  * 如果 count < 0,则抛出 IllegalArgumentException 异常
  */
public CountDownLatch(int count)

CountDownLatch 其实实现比较简单,也只提供了如下一个构造函数

常用 API

/**
  * 初始化 CountDownLatch 后调用该方法,用于等待倒数计数为 0
  * 如果计数一直不为 0,则一直等待。除非线程被打断,打断后抛出 InterruptedException 异常
  * 底层是AQS  acquire 操作(获取锁)
  */
public void await() throws InterruptedException
/**
  * 初始化 CountDownLatch 后调用该方法,用于等待倒数计数为 0
  * 如果计数一直不为 0,则等待最长 timeout 时间。如果时间到了,计数还是不为 0 ,则返回 false,否则返回 true
  * 除非线程被打断,打断后抛出 InterruptedException 异常
  */
public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException
/**
  * 调用一次计数减一,如果计数已经为0,则不会有什么效果
  * 底层是 AQS release 方法(释放锁)
  */
public void countDown()
/**
  * 返回当前计数(注意:此方法只在调试和测试时调用)
  * 不要用作业务判断,计数为0,所有 await 的线程都会取消阻塞
  */
public long getCount()

示例

import lombok.extern.slf4j.Slf4j;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@Slf4j
public class CountDownLatchTest {

    public static void main(String[] args) {

        // 运动员个数
        int num = 8;
        CountDownLatch runner = new CountDownLatch(num);

        for (int i = 0; i < num; i++) {

            new Thread(()->{

                log.debug("开始执行");
                long time = 9000 + new Random().nextInt(5000);
                try {
                    TimeUnit.MILLISECONDS.sleep(time);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                log.debug("执行完毕,用时:{}",time);
                runner.countDown();

            },"线程"+i).start();

        }

        try {
            // 阻塞等待其他线程执行完毕,main 线程才会执行
            runner.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.debug("等待其他线程执行完毕");



    }

}

CyclicBarrier

CyclicBarrier翻译过来就是:循环屏障。各个线程之间相互等待,等最后一个线程准备完毕,一起执行。

原理

CyclicBarrier 内部使用 ReentrantLock 实现。

构造方法

/**
  * @Param parties 参与的线程数(计数)
  */
public CyclicBarrier(int parties)
/**
  * @Param barrierAction 表示当参与的线程都执行完成后,要执行的任务
  */
public CyclicBarrier(int parties, Runnable barrierAction)

常用 API

// 获取当前的CyclicBarrier一共有多少线程参数与
public int getParties()

// 等待(如果有线程在等待中,调用 reset 方法,会抛出 BrokenBarrierException)
public int await() throws InterruptedException, BrokenBarrierException
public int await(long timeout, TimeUnit unit)
        throws InterruptedException,
               BrokenBarrierException,
               TimeoutException

// 判断barrier是否已经损坏
public boolean isBroken()

// 重置barrier,重复使用前调用
public void reset()

// 获取当前正在等待该barrier的线程数
public int getNumberWaiting()

示例

田径比赛中,最后一个运动员准备好之后,发令起跑,最先到达终点的为第一名

import lombok.extern.slf4j.Slf4j;

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;

@Slf4j
public class CyclicBarrierTest {

    public static void main(String[] args) throws InterruptedException {

        int num = 8;
        CyclicBarrier barrier = new CyclicBarrier(num,()->{
            // 执行这个任务的是最后一个准备的线程
            log.debug("都准备好了,开跑");
        });

        for (int i = 0; i < num; i++) {
            new Thread(()->{

                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } catch (BrokenBarrierException e) {
                    throw new RuntimeException(e);
                }
                // 模拟到达时间(一般百米在9到14秒以内)
                long time = 9000 + new Random().nextInt(5000);
                try {
                    TimeUnit.MILLISECONDS.sleep(time);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                log.debug("到达终点,用时:{}",time);

            },"运动员"+i).start();
        }

    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1368215.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android readelf 工具查找函数符号

ELF&#xff08;Executable and Linkable Format&#xff09;是一种执行文件和可链接文件的格式。它是一种通用的二进制文件格式&#xff0c;用于在各种操作系统中存储可执行程序、共享库和内核模块。 Android 开发当中的 so 库本质上就是一种特殊类型的 ELF 文件&#xff0c;…

【JAVA GUI+MYSQL]社团信息管理系统

本社团信息管理系统主要实现登录注册、管理员信息管理、社团用户信息管理、用户申请信息管理功能模块。 目录 &#xff11;&#xff0e;系统主要功能介绍 &#xff12;&#xff0e; 数据库概念模型设计 3.具体功能模块的实现 3.1模型类 3.1.1Student.java 3.1.2User .j…

HarmonyOS应用开发学习笔记 UIAbility组件与UI的数据同步 EventHub、globalThis

1、 HarmoryOS Ability页面的生命周期 2、 Component自定义组件 3、HarmonyOS 应用开发学习笔记 ets组件生命周期 4、HarmonyOS 应用开发学习笔记 ets组件样式定义 Styles装饰器&#xff1a;定义组件重用样式 Extend装饰器&#xff1a;定义扩展组件样式 5、HarmonyOS 应用开发…

Linux基础知识点(九-POSIX信号量)

目录 一、基本概念 二、有名信号量 三、无名信号量 一、基本概念 信号量&#xff08;Semaphore&#xff09;是一种实现进程/线程间通信的机制&#xff0c;可以实现进程/线程之间同步或临界资源的互斥访问&#xff0c; 常用于协助一组相互竞争的进程/线程来访问临界资源。在多…

洛谷 P1217 [USACO1.5] 回文质数 Prime Palindromes 刷题笔记

P1217 [USACO1.5] 回文质数 Prime Palindromes - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路 直接枚举 减枝优化判断 优化1 只有偶数才会是质数 优化2 回文数的判断次数要优于检查素数 先判断是否为回文数再检查是否为质数 if( hw(i)&&isprime(i)) 这里…

前端根据URL地址实现下载(txt,图片,word,xlsx,ppt)

前端根据URL地址实现下载&#xff08;txt&#xff0c;图片&#xff0c;word&#xff0c;xlsx&#xff0c;ppt&#xff09; 一、对于txt,图片类的二、对于word&#xff0c;xlsx&#xff0c;ppt类的1.a标签可以实现下载2. window.open&#xff08;&#xff09; 一、对于txt,图片类…

Dijkstra算法——邻接矩阵实现+路径记录

本文是在下面这篇文章的基础上做了一些补充&#xff0c;增加了路径记录的功能。具体Dijkstra的实现过程可以参考下面的这篇文章。 [jarvan&#xff1a;Dijkstra算法详解 通俗易懂](Dijkstra算法详解 通俗易懂 - jarvan的文章 - 知乎 https://zhuanlan.zhihu.com/p/338414118) …

一方水土,一方气运

峰民风水悟语&#xff1a;“地灵人杰”&#xff0c;一方好水土&#xff0c;养育一方好人才。风水&#xff0c;就是一个地方的山水之气&#xff0c;会影响一个地方的人。正所谓&#xff1a;“山清水秀出美人&#xff0c;穷山恶水出刁民”就是这个理。 古人认为环境的能量磁场能控…

oracle19c容器数据库rman备份特性-----性能优化(三)

目录 冗余备份片 1.备份的时候指定 2.rman配置中设定 归档备份&#xff08;将备份集保留&#xff09; 二级备份&#xff08;将备份文件保留&#xff09; 1.备份闪回恢复区的恢复文件 2.备份所有恢复文件 recovery catalog database 1.創建recovery catalog 2.创建VPC…

cocos creator 如何绑定参数到编辑器

很多cocos creator同学不知道如何绑定组件属性到编辑器上&#xff0c;今天我们来教大家如何绑定 1: 基本数据属性绑定到编辑器 这个非常简单&#xff0c;模板是属性名字: 默认的值; Is_debug: false, speed: 100, 2: 系统组件类型与节点绑定到编辑器 属性名字: { type: 组件…

少儿编程 中国电子学会图形化编程2022年9月等级考试Scratch二级真题解析(选择题、判断题)

一、单选题(共25题&#xff0c;每题2分&#xff0c;共50分) 一、单选题(共25题&#xff0c;共50分) 1.数列&#xff1a;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;6&#xff0c;9&#xff0c;13&#xff0c;19&#xff0c;28&#xff0c;...的下一项是多少&#…

竞赛保研 基于深度学习的人脸性别年龄识别 - 图像识别 opencv

文章目录 0 前言1 课题描述2 实现效果3 算法实现原理3.1 数据集3.2 深度学习识别算法3.3 特征提取主干网络3.4 总体实现流程 4 具体实现4.1 预训练数据格式4.2 部分实现代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 毕业设计…

第二百五十四回

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了"如何给图片添加阴影"相关的内容&#xff0c;本章回中将介绍自定义Radio组件.闲话休提&#xff0c;让我们一起Talk Flutter吧…

Spark 初级编程实践

什么是Spark? Spark是一个快速、通用、可扩展的大数据处理引擎,最初由加州大学伯克利分校的AMPLab开发。它提供了高级API,用于在大规模数据集上执行并行处理。Spark支持多种编程语言,包括Java、Scala、Python和R,因此被广泛应用于大数据分析和机器学习等领域。 一、目的 …

认识Linux指令之 “ 重定向” 符号

01.echo命令 在Linux中&#xff0c;我们可以使用echo命令打印 02. > 输出重定向 在111文件夹中我们只有dir文件夹和file.txt文件 用 echo > &#xff08;输出重定向&#xff09;我们可以将内容输入对应的文件中 也可以直接重定向 > >的作用 创建文件&#xff08…

【MATLAB】小波_LSTM神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 小波-LSTM神经网络时序预测算法是一种结合了小波变换和长短期记忆神经网络&#xff08;LSTM&#xff09;的时间序列预测方法。 小波变换是一种信号处理方法&#xff0c;能够将信号分解为…

.NET国产化改造探索(五)、结合Nginx并确保.NET应用程序自动启动

随着时代的发展以及近年来信创工作和…废话就不多说了&#xff0c;这个系列就是为.NET遇到国产化需求的一个闭坑系列。接下来&#xff0c;看操作。 上一篇介绍了如何在银河麒麟操作系统上安装Nginx&#xff0c;这篇文章详细介绍下在银河麒麟操作系统上&#xff0c;使用Nginx.N…

vue3 封装一个Tooltip 文字提示组件

效果图 默认展示icon图标&#xff0c;悬浮展示文字 如果slot有内容则展示对应内容 实现 用的是El-Tooltip组件 Element - The worlds most popular Vue UI framework 组件代码 <script setup lang"ts"> import { Icon } from /components/Icon import { ElTo…

《剑指offer》专项突破

第一章:整数 面试题1:整数除法 题目 输入两个int型整数,求它们除法的商,要求不得使用乘号’*‘、除号’/‘以及求余符号’%。当发生溢出时返回最大的整数值。假设除数不为0。例如,输入15和2,输出15/2的结果,即7。 参考代码 public int divide(int dividend, int di…

数字孪生与数据可视化大屏

什么是数字孪生 数字孪生技术是一种在现实世界中模拟虚拟世界的技术,它可以将物理世界中的各种事物、过程、行为等转化为虚拟世界中的数据模型,从而实现虚拟世界与现实世界的互动。数字孪生技术可以应用于能源管理、建筑能耗评估、设备全生命周期管理等领域,它可以帮助企业…