Java并发编程(8)-Semaphore

征服Java多线程并发编程:8大高级模式与实践,让你的代码飞起来! 记住,多线程编程是一把双刃剑,既能显著提升程序性能,也带来了复杂的同步问题和调试难度。希望这篇文章能为你的多线程学习之路提供有价值的指导和启发,让我们的代码在多线程的世界里翩翩起舞!别担心,今天我们将带你深入探索Java多线程并发编程的世界,通过介绍8种高级模式与最佳实践,让你的程序既快又稳。在Java中,多线程是指在一个程序中同时运行多个线程,每个线程都可以独立执行任务。在这个例子中,我们不仅学会了如何正确地分配资源,还掌握了避免死锁的基本技巧。确保所有线程按照相同的顺序请求资源,并合理使用超时机制。 阅读详情


更多关于Java并发编程的文章请点击这里:Java并发编程实践(0)-目录页


在Java并发编程中,信号量(Semaphore类)可视为synchronized的升级,它能控制一个程序中线程的数量,负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。

一、Semaphore信号量

1.1、什么是信号量

以一个停车场是运作为例。为了简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。
在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。
更进一步,信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。 当一个线程调用Wait(等待)操作时,它要么通过然后将信号量减一,要么一直等下去,直到信号量大于一或超时。Release(释放)实际上是在信号量上执行加操作,对应于车辆离开停车场,该操作之所以叫做“释放”是因为加操作实际上是释放了由信号量守护的资源。
在java中,还可以设置该信号量是否采用公平模式,如果以公平方式执行,则线程将会按到达的顺序(FIFO)执行,如果是非公平,则可以后请求的有可能排在队列的头部。
JDK中定义如下:
Semaphore(int permits, boolean fair)
  创建具有给定的许可数和给定的公平设置的Semaphore。 --百度百科

1.2、信号量在并发编程中的作用

在Java并发编程中,信号量(Semaphore类)可视为synchronized的升级,它能控制一个程序中线程的数量,负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。

二、Semaphore类简单解读

Semaphore类位于java.util.concurrent并发包之下,它是信号量的具体实现类。

2.1、构造方法解读

(1)、public Semaphore(int permits)
用给定的许可数和非公平的公平设置创建一个 Semaphore,即线程不按照FIFO的方式执行。

参数:
permits - 初始的可用许可数目。此值可能为负数,在这种情况下,必须在授予任何获取前进行释放。

(2)、public Semaphore(int permits, boolean fair)
用给定的许可数和给定的公平设置创建一个 Semaphore,保证线程的执行是FIFO方式的。

参数:
permits - 初始的可用许可数目。此值可能为负数,在这种情况下,必须在授予任何获取前进行释放。
fair - 如果此信号量保证在争用时按先进先出的顺序授予许可,则为 ture,否则为 false。

2.2、常用方法解读

(1)、acquire方法
public void acquire() throws InterruptedException
从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。 获取一个许可(如果提供了一个)并立即返回,将可用的许可数减 1。
如果没有可用的许可,则在发生以下两种情况之一前,禁止将当前线程用于线程安排目的并使其处于休眠状态:

①某些其他线程调用此信号量的 release() 方法,并且当前线程是下一个要被分配许可的线程;
②其他某些线程中断当前线程。

(2)、tryAcquire方法
①public boolean tryAcquire()
仅在调用时此信号量存在一个可用许可,才从信号量获取许可。
获取一个许可(如果提供了一个)并立即返回,其值为 true,将可用的许可数减 1。 如果没有可用的许可,则此方法立即返回并且值为 false。

② public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException
如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被中断,则从此信号量获取给定数目的许可。
获取给定数目的许可(如果提供了)并立即返回,其值为 true,将可用的许可数减去给定的量。

如果没有足够的可用许可,则在发生以下三种情况之一前,禁止将当前线程用于线程安排目的并使其处于休眠状态:

①其他某些线程调用此信号量的某个释放方法,当前线程是下一个被分配许可的线程,并且可用许可的数目满足此请求;

②其他某些线程中断当前线程;

③ 已超出指定的等待时间。

(3)、availablePermits方法
public int availablePermits()
返回此信号量中当前可用的许可数。 此方法通常用于调试和测试目的。

(4)、release方法
public void release(int permits)
释放给定数目的许可,将其返回到信号量。
释放给定数目的许可,将可用的许可数增加该量。如果任意线程试图获取许可,则选中某个线程并将刚刚释放的许可给予该线程。如果可用许可的数目满足该线程的请求,则针对线程安排目的启用(或再启用)该线程;否则在有足够的可用许可前线程将一直等待。如果满足此线程的请求后仍有可用的许可,则依次将这些许可分配给试图获取许可的其他线程。

三、简单程序解读

@Test
    public void semaphoreTest(){
        Semaphore semaphore = new Semaphore(3);

        ExecutorService executorService = Executors.newFixedThreadPool(2);
        for (int i = 0; i < 5; i++) {
            executorService.execute(new Runnable(){
                Semaphore semaphore1 = semaphore;
                public void run(){

                    try {
                        semaphore1.acquire();//获取信号量,执行程序
                        System.out.println(Thread.currentThread().getName()+"获得信号量,开始执行程序...,剩余信号量:"+semaphore1.availablePermits());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        semaphore1.release();//释放信号量
                        System.out.println("线程"+Thread.currentThread().getName()+"释放信号量,剩余信号量:"+semaphore1.availablePermits());
                    }

                }
            });
        }
    }

在这里插入图片描述如果我们不释放信号量。那么3信号量被消耗完,程序也就是循环到第3次的时候,程序就已经结束了,因为没有信号量,线程也就没有权利执行程序。

		finally {
                       // semaphore1.release();//释放信号量
                        //System.out.println("线程"+Thread.currentThread().getName()+"释放信号量,剩余信号量:"+semaphore1.availablePermits());
                        System.out.println("剩余信号量:"+semaphore1.availablePermits());

                    }

在这里插入图片描述

四、公平模式和非公平模式

1.公平模式

根据acquire的顺序来获取许可证,遵循FIFO。

2.非公平模式

即抢占式获取许可证。这是默认情况。

可在构造信号量时通过构造函数去设置这两种模式:

    // 默认是非公平的
    public Semaphore(int permits) {
        sync = new NonfairSync(permits);
    }

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

Keil MDK编译错误#541解决方案与ARM_Compiler包解析 在嵌入式开发中,编译器工具链的依赖管理是确保项目顺利构建的关键环节。以Keil MDK为例,其软件包依赖机制通过组件化设计实现功能解耦,其中ARM_Compiler包专门处理系统IO重定向等编译器扩展功能。这种架构既提升了模块复用性,也带来了版本兼容性挑战。当出现'Error #541: component missing'报错时,通常是由于中间件组件(如文件系统)在新版本中显式依赖了ARM_Compiler包。开发者需要通过Pack Installer安装该包,并在Run-Time Environment 阅读详情

相关推荐

Nuclei漏洞扫描:从零到精通的Windows实战指南

本文详细介绍了Nuclei漏洞扫描工具在Windows平台上的安装与使用教程,从基础安装到高级实战技巧全面覆盖。通过具体案例展示如何利用Nuclei的模板库快速检测常见漏洞,并提供自定义POC开发指南,帮助安全从业者高效开展漏洞扫描工作。

weixin_28683689的博客 251

Semaphore小述

1.概述 Semphore(信号量)是一种线程同步工具,它主要用于多个线程对同一个资源进行并行操作,合理并发占用有限的公共资源。Semaphore可以理解为管理一组数量固定许可证的机构,当有大量线程来请求资源时,Semaphore会给一部分线程许可证,拿到许可证的线程才能访问资源,访问结束后归还许可证给Semaphore,Semaphore继续将证书发给排队的一个个线程;使用Semaphore可以控制并发资源的线程个数。本文将通过案例对Semaphore进行演示,并通过源码进行分析,从而全面展示Semaph

qq_33479841的博客 942

水电站数字孪生:水力发电在可视化领域的应用

为智慧水坝领域提供了 B/S 架构的基于 WebGL 的图形引擎,与 GIS、粒子仿真、虚拟现实、边缘计算等技术相结合,融合多元业务系统数据,形成数字孪生界面,助力水利水电工程进一步提升数字化水平,乃至为整个工业领域添砖加瓦。

二三维数据可视化/数字孪生 2255

Semaphore详解

判断是否满足获取锁条件,关键方法.若获取锁成功,则也会修改state.若获取锁失败,关键方法阻塞的获取锁.添加到双向链表若是头节点后继,则尝试获取锁,否者则判断进入睡眠等待唤醒,唤醒后继续执行3.2若不进入睡眠,则直接运行到3.2步释放N个许可,因为存在并发释放,需要CAS确保设置更新后的值.唤醒双向链表中有效的等待节点.(可能存在并发问题,引入PROPAGATE状态)被唤醒的节点调用获取锁的流程....

Admans的专栏 2万+

GEE AI: 利用 Satellite Embedding 语义搜索快速识别研究区目标斑块

摘要 本文介绍了一种基于Google Earth Engine的遥感语义搜索技术,利用Satellite Embedding数据集快速识别目标地物。该方法通过将光谱信息转化为高维向量,在武汉市的案例中展示了如何:1)定义研究区和样本点;2)加载预处理的Embedding数据;3)计算向量相似度;4)结合面积过滤优化结果。相比传统监督分类,该技术具有响应快速(无需模型训练)、抗季节干扰和精准界定等优势,特别适用于森林碳储量监测和土地利用检测等应用场景。文中提供了完整的GEE代码实现流程,包括样本定义、相似度计

此星光明博客 625

摩尔线程GPU实战:5分钟搞定AI模型部署(含Docker避坑指南)

本文详细介绍了摩尔线程GPU在AI模型部署中的实战应用,包括环境配置、Docker避坑指南及性能优化技巧。通过5分钟快速部署指南,帮助开发者高效利用摩尔线程GPU进行AI模型推理,特别针对常见兼容性问题提供解决方案,显著提升部署效率。

weixin_28736335的博客 454

Java并发编程三大神器之Semaphore

1、Semaphore是什么 2、Semaphore小试牛刀 3、Semaphore和CountDownLatch组合使用 4、Semaphore常用方法 5、Semaphore 结语

michael_linux的博客,一个小小小学生。滴水穿石,步步为营,只为那刹那芳华。 1723

【人工智能】你知道什么是DeepSeek吗?你有去了解过DeepSeek吗?新手要入门DeepSeek的必经之路——初识DeepSeek

【人工智能】初识DeepSeek 详细介绍DeepSeek以及DeepSeek-R1

蒙奇D索大的博客 3410

互斥锁和信号量(多线程)

信号量(semphore):多线程多任务同步,一个线程占用此资源后,通过信号量同步状态给别的线程。 互斥锁(Mutual exclusion):多线程多任务互斥,一个线程占用资源后,必须等待释放。(常用) mutex是semphore一种特殊情况(n=1),后者可以代替前者。mute效率高简单,一般需要加锁的地方常用mutex。 多个线程抢锁,测试看貌似是随机抢到的。 测试: //模拟单锁多线程占用 #include<pthread.h> #include<semaphore.h>

yaenbb1的博客 1072

YOLOv9分割训练自己数据和推理训练好模型,并教你使用Labelme工具标注数据(附YOLOv9分割模型结构图),全网最详细教程

YOLOv9 通过研究数据传输时的信息丢失问题,提出了可编程梯度信息(PGI)和通用高效层聚合网络(GELAN)架构,提高了参数利用率和模型性能。与 SOTA 方法相比,GELAN 仅使用传统卷积算子即可实现更好的参数利用率。PGI 适用于从轻型到大型的各种模型,使从头开始训练的模型能够获得更好的结果。YOLOv9 被评价为新的 SOTA 实时目标检测器。接下来本文手把手教你训练自己分割数据集和推理训练好的分割模型。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 1493

【机器人学】常用的小车底盘运动学模型推导(附C++代码)

认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长!本文先对小车底盘运动学模型介绍做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章提示:以下是本篇文章正文内容对于小车的分析,仅仅考虑XY轴的线速度和Z轴的角速度,不考虑和横滚和俯仰的速度,【防盗标记–盒子君hzj】也不考虑Z轴的高度变化【即:车底盘的运动可以用三个独立变量来描述:x轴平动、y轴平动、yaw轴转动】

qq_35635374的博客 1932

Semaphore 详解

可以把它简单的理解成我们停车场入口立着的那个显示屏,每有一辆车进入停车场显示屏就会显示剩余车位减1,每有一辆车从停车场出去,显示屏上显示的剩余车辆就会加1,当显示屏上的剩余车位为0时,停车场入口的栏杆就不会再打开,车辆就无法进入停车场了,直到有一辆车从停车场出去为止。每个停车场入口都有一个提示牌,上面显示着停车场的剩余车位还有多少,当剩余车位为0时,不允许车辆进入停车场,直到停车场里面有车离开停车场,这时提示牌上会显示新的剩余车位数。3、每有一辆车驶出停车场后,显示牌的剩余车位数响应的加1。

qq_58148854的博客 2607

华为OD机试2025A卷 - BOSS的收入(Java & Python& JS & C++ & C )

华为OD机试2025A卷 - BOSS的收入(Jav一个XX产品行销总公司,只有一个boss,其有若干一级分销,一级分销又有若干二级分销,每个分销只有唯一的上级分销。规定,每个月,下级分销需要将自己的总收入(自己的+下级上交的)每满100元上交15元给自己的上级。现给出一组分销的关系,和每个分销的收入,请找出boss并计算出这个boss的收入。输入:分销关系和收入:[[分销id 上级分销id 收入], [分销id 上级分销id 收入], [分销id 上级分销id 收入]]输出:[boss的ID, 总收入]

算法大师! 1173

Java并发编程:AbstractQueuedSynchronizer之Semaphore源码分析1.8

Semaphore

weixin_43185598的博客 177

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Java并发编程基础---(8)控制并发编程数量的Semaphore总结

写在前面:    在前面两篇博客中,介绍了CountDownLatch、CyclicBarrier类的使用,这篇博客中,将会总结Semaphore类的使用,完善Java并发包中的3个工具类的使用总结。Semaphore    Semaphore是用来控制程序中并发访问一个特定资源的线程数量,Semaphore通过协调各个线程,从而保证了资源的调度。Semaphore的构造器    我们来看一下JD...

To be a better man的博客 312

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Java 8 并发编程实战指南:从线程基础到高级并发工具

在现代计算机系统中,并发编程已成为开发者必须掌握的核心技能之一。Java 从最初版本就内置了对多线程的支持,而 Java 8 则进一步丰富了并发编程的工具集。理解并发编程的基础概念对于编写高效、可靠的应用程序至关重要。 ### 线程基础:Thread 和 Runnable Java 中的并发执行单元是线程,它比进程更轻量级,共享进程的内存空间。创建线程有两种基本方式: 1. 继承 Threa

gitblog_00344的博客 450

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java并发编程面试题:并发工具类(10题)

①、HashMap 是非线程安全的,多线程环境下应该使用 ConcurrentHashMap。②、由于 HashMap 仅在单线程环境下使用,所以不需要考虑同步问题,因此效率高于 ConcurrentHashMap。

在技术的广袤天地里,本博客如精准罗盘。剖析前沿科技,深掘代码奥秘,以精炼笔触,带您穿越复杂技术迷宫,速达知识彼岸。 1426

JUC并发编程与源码分析笔记01-本课程前置知识及要求说明

课程使用IDEA来讲解,要求熟练使用IDEA相关操作。

王劭阳的博客 752

Java岗:十余年实战经验积累,进大厂必备:三位阿里P8大牛精心整理的笔记《并发编程核心讲义》

这主要是硬件的驱动以及国内互联网行业的飞速发展决定的,现在 64 核的服务器已经飞入寻常百姓家,大型互联网厂商的系统并发量轻松过百万,传统的中间件和数据库已经不能为我们遮风挡雨,反而成了瓶颈所在。于是,并发编程成为近年非常热门的领域,人才稀缺。但与此同时,关于并发编程的书籍也渐渐丰富起来了,庞杂而且生涩难懂。经过这些年接触,我发现很多小伙伴,都是工作几年后很多技术突飞猛进,只有并发编程成为瓶颈,并发相关的类库他们也熟悉,却总是写不出正确、高效的并发程序,原因在哪里?

weixin_66896902的博客 607

Java Semaphore 与 ReentrantReadWriteLock:区别、实现与适用场景

在 Java 并发编程中, 和 是 包中两种重要的同步工具,用于管理多线程访问共享资源。根据 2024 年 Stack Overflow 开发者调查,Java 占编程语言使用率的 30%,在高并发场景(如电商、微服务)中表现突出。 通过计数器控制资源访问许可,而 提供读写分离的锁机制,两者适用于不同场景。本文深入剖析 和 的原理、区别、优缺点及适用场景,并以电商库存查询与更新系统(QPS 10 万,P99 延迟 < 10ms)为例,展示如何选择和使用两者。 公平性:支持公平(FIFO)和非公平模

lssffy的博客 920

《Java线程与并发编程实践》—— 导读

前言 Java线程与并发编程实践线程和并发工具并非尤物,但是它们是正式应用的重要部分。本书会向你介绍Java 8 Update 60中线程特性以及并发工具的大部分内容。 第1章介绍了类Thread和接口Runnable。你会学习如何创建Thread以及Runnable对象,获取和设置线程状态、启动线程、中断线程,将一条线程插入另外一条线程以及触发...

weixin_34337265的博客 155

Java并发编程(三)——ThreadLocal、AQS、线程安全集合类

Java并发编程(三)——ThreadLocal、AQS、线程安全集合类一、ThreadLocal详解1.1 ThreadLocal的使用1.2 ThreadLocal实现原理1.3 ThreadLocal内存泄漏1.3.1 强、软、弱、虚、四大引用1.3.2 原因分析二、AQS详解2.1 AQS介绍2.2 AQS源码分析2.3 ReentrantLock2.4 ReentrantReadWriteLock读写锁2.5 Semaphore2.6 CountdownLatch2.7 CyclicBarrier

weixin_44630656的博客 1158

精通 Java8 并发编程(三)

毫无疑问,Java 8 引入的最重要的创新是 lambda 表达式和 stream API。流是可以按顺序或并行方式处理的元素序列。我们可以应用中间操作来转换流,然后执行最终计算以获得所需的结果(列表、数组、数字等)。在本章中,我们将涵盖以下主题:流的介绍第一个例子-数字摘要应用程序第二个例子-信息检索搜索工具流是一系列数据(不是数据结构),允许您以顺序或并行方式应用一系列操作来过滤、转换、排序、减少或组织这些元素以获得最终对象。例如,如果您有一个包含员工数据的流,您可以使用流来:计算员工的总数计算居住在特

龙哥盟 902

Java 并发编程(七)|JUC 工具类与线程安全集合考点

上一篇我们讲解了各类锁策略、CAS 无锁编程、synchronized 底层锁升级优化。本篇聚焦并发工程实战内容,完整梳理 JUC 包核心工具类与各类线程安全集合,覆盖 Callable、ReentrantLock、Semaphore、CountDownLatch 以及 ConcurrentHashMap 等高频面试考点,配套可运行案例,补齐 Java 并发编程业务落地相关知识点。Callable+FutureTask 实现带返回值线程;

2401_88393233的博客 230

Java8中JUC包同步工具类深度解析(Semaphore,CountDownLatch,CyclicBarrier,Phaser)

工具类主要用途内部原理使用场景Semaphore控制访问某个或多个共享资源的线程数量基于AQS实现,维护一个许可计数器需要限制并发访问共享资源的场景,如连接池、线程池等允许一个或多个线程等待其他线程完成操作基于AQS实现,维护一个计数器用于协调一组线程的执行顺序,例如启动多个线程并行处理任务,并在所有任务完成后执行汇总操作让一组线程互相等待,直到所有线程都到达某个公共屏障点使用锁和条件变量实现,维护屏障的周期和计数器。

1688

并发工具类:如何在JDK 8、17与21中使用CountDownLatch、Semaphore和CyclicBarrier?

并发工具类:如何在JDK 8、17与21中使用CountDownLatch、Semaphore和CyclicBarrier?

猫头虎技术团队:授渔优于赠鱼,兴趣引领智慧,探索之乐尤显珍贵。商务合作+:Libin9iOak ,万粉变现+:优快云WF,猫头虎承诺每年免费为100名C站创作者做账号流量诊断服务!全网搜:猫头虎技术团队,点击文章底部名片或直接私信我一切皆可谈,快找虎哥! 2798
上一篇: Java并发编程(7)-ThreadPoolExecutor的饱和策略
下一篇: Java并发编程(9)-CountDownLatch
BoringRong
BoringRong 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 2万+粉丝 386原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BoringRong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值