news 2026/5/7 19:05:20

Java面试必看!Semaphore的作用及实战案例解析!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java面试必看!Semaphore的作用及实战案例解析!

文章目录

  • Java面试必看!Semaphore的作用及实战案例解析!
    • 引言
    • 一、Semaphore的基本概念
      • 1.1 什么是Semaphore?
      • 1.2 Semaphore的工作原理
    • 二、Semaphore的核心方法
      • 2.1 acquire() 方法
      • 2.2 release() 方法
      • 2.3 getQueueLength() 方法
      • 2.4 availablePermits() 方法
    • 三、Semaphore的应用场景
      • 3.1 控制并发数
      • 3.2 替代ReentrantLock
      • 3.3 实现信号量机制
    • 四、总结
    • 希望本文能够帮助大家更好地理解和使用Java中的`Semaphore`!
      • 📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

Java面试必看!Semaphore的作用及实战案例解析!

引言

各位小伙伴们,大家好啊!闫工又来给大家讲解Java面试中的知识点啦!今天咱们要聊的是一个非常重要的同步工具——** Semaphore(信号量)**。这可是Java多线程编程中不可或缺的一部分,掌握它不仅能让你在面试中脱颖而出,还能在实际开发中游刃有余。

相信很多小伙伴都听说过Semaphore这个词,但可能对它的具体作用和使用场景还不是很清楚。没关系,今天闫工就带着大家一起深入了解 Semaphore 的前世今生,从理论到实战,手把手教大家如何玩转这个强大的工具!

一、Semaphore的基本概念

1.1 什么是Semaphore?

Semaphore(信号量)是Java中用于控制同时访问特定资源的线程数量的一种同步工具。它就像一个交通警察,负责协调多个线程对共享资源的访问,确保系统的稳定性和高效性。

在多线程编程中,我们经常需要限制某些资源的并发访问数,比如数据库连接池、文件读写操作等。Semaphore就可以很好地解决这个问题,它可以控制同时访问这些资源的线程数量,从而避免资源被过度使用或者发生竞争。

1.2 Semaphore的工作原理

Semaphore的核心思想是基于许可(permits)机制。每个信号量都有一个固定的许可数量,当线程想要访问受控资源时,必须先获取一个许可;如果所有许可都被占用,那么该线程就会被阻塞,直到有其他线程释放许可。

举个简单的例子:假设我们有一个Semaphore对象,初始化时设置为3。这意味着最多允许3个线程同时访问某个资源。当第4个线程试图访问这个资源时,它会被阻塞,直到其中一个线程释放许可为止。

二、Semaphore的核心方法

在Java中,Semaphore类位于java.util.concurrent包下,提供了以下几个核心方法:

2.1 acquire() 方法

publicvoidacquire()throwsInterruptedException
  • 作用:尝试获取一个许可。如果没有可用的许可,线程会被阻塞,直到有其他线程释放许可。
  • 异常:如果当前线程被中断,则会抛出InterruptedException。

2.2 release() 方法

publicvoidrelease()
  • 作用:释放一个许可,使得其他等待的线程可以继续执行。

2.3 getQueueLength() 方法

publicintgetQueueLength()
  • 作用:返回正在等待获取许可的线程数量。

2.4 availablePermits() 方法

publicintavailablePermits()
  • 作用:返回当前可用的许可数量。

三、Semaphore的应用场景

Semaphore在实际开发中有着广泛的应用,以下是几个常见的使用场景:

3.1 控制并发数

最常见的应用场景就是控制系统的并发线程数。例如,在数据库连接池中,我们通常会限制同时访问数据库的线程数量,以避免服务器过载。

示例代码:

importjava.util.concurrent.Semaphore;publicclassDatabaseConnection{privatestaticfinalintMAX_CONNECTIONS=5;privatestaticSemaphoresemaphore=newSemaphore(MAX_CONNECTIONS);publicvoidgetConnection(){try{// 尝试获取一个许可,最多等待10秒if(semaphore.tryAcquire(10,TimeUnit.SECONDS)){System.out.println(Thread.currentThread().getName()+" 获取到数据库连接");// 模拟数据库操作Thread.sleep(2000);semaphore.release();// 释放许可}else{System.out.println(Thread.currentThread().getName()+" 获取数据库连接超时,放弃请求");}}catch(InterruptedExceptione){Thread.currentThread().interrupt();System.out.println(Thread.currentThread().getName()+" 被中断,退出获取连接操作");}}publicstaticvoidmain(String[]args){DatabaseConnectiondb=newDatabaseConnection();for(inti=0;i<10;i++){Threadthread=newThread(db::getConnection,"Thread-"+i);thread.start();}}}

解释:

  • 我们创建了一个Semaphore对象,初始化时设置为5个许可。
  • 每个线程调用getConnection()方法尝试获取一个许可。最多只能有5个线程同时访问数据库。
  • 如果某个线程在10秒内没有获得许可,则会放弃请求。

3.2 替代ReentrantLock

Semaphore还可以用来替代ReentrantLock,实现更灵活的锁机制。

示例代码:

importjava.util.concurrent.Semaphore;publicclassCounter{privateintcount=0;privateSemaphoresemaphore=newSemaphore(1);// 初始化为1个许可publicvoidincrement(){try{semaphore.acquire();// 获取锁count++;System.out.println(Thread.currentThread().getName()+" 增加到:"+count);Thread.sleep(1000);// 模拟操作时间semaphore.release();// 释放锁}catch(InterruptedExceptione){Thread.currentThread().interrupt();System.out.println(Thread.currentThread().getName()+" 被中断,退出");}}publicstaticvoidmain(String[]args){Countercounter=newCounter();for(inti=0;i<5;i++){Threadthread=newThread(counter::increment,"Thread-"+i);thread.start();}}}

解释:

  • 我们使用Semaphore来实现互斥锁,确保只有一个线程可以执行increment()方法。
  • 这个示例展示了如何将Semaphore作为互斥锁的替代品。

3.3 实现信号量机制

Semaphore最经典的用途就是实现信号量机制。例如,在操作系统中,多个进程需要共享某个资源时,可以通过信号量来协调它们的行为。

示例代码:

importjava.util.concurrent.Semaphore;publicclassSignalExample{privatestaticfinalSemaphoreavailableSem=newSemaphore(0);// 初始没有可用的许可privatestaticfinalSemaphorebusySem=newSemaphore(1);// 初始有一个许可publicstaticvoidmain(String[]args){// 创建生产者线程ThreadproducerThread=newThread(()->{for(inti=0;i<5;i++){try{System.out.println("生产者正在生产...");busySem.acquire();// 等待消费者释放许可availableSem.release();// 通知消费者可以消费了Thread.sleep(100);// 模拟生产时间}catch(InterruptedExceptione){Thread.currentThread().interrupt();System.out.println("生产者被中断,退出");}}},"Producer");// 创建消费者线程ThreadconsumerThread=newThread(()->{for(inti=0;i<5;i++){try{availableSem.acquire();// 等待生产者的通知System.out.println("消费者正在消费...");busySem.release();// 通知生产者可以继续生产了Thread.sleep(100);// 模拟消费时间}catch(InterruptedExceptione){Thread.currentThread().interrupt();System.out.println("消费者被中断,退出");}}},"Consumer");producerThread.start();consumerThread.start();}}

解释:

  • availableSem表示生产者已经生产了商品。
  • busySem表示消费者正在消费商品。
  • 生产者线程在每次生产后都会释放一个availableSem的许可,通知消费者可以开始消费。
  • 消费者线程在每次消费后都会释放一个busySem的许可,通知生产者可以继续生产。

四、总结

通过以上示例可以看出,Semaphore是一个非常强大的工具,它可以用来控制并发数、实现互斥锁以及协调多个线程之间的行为。但在实际使用中,需要注意以下几点:

  1. 线程安全:在多线程环境下,一定要确保Semaphore的操作是原子性的。
  2. 异常处理:当使用acquire()方法时,如果被中断,应该及时释放资源,并进行相应的处理。
  3. 性能问题:虽然Semaphore提供了灵活性,但在某些情况下,可能会引入额外的性能开销。因此,在设计系统时需要权衡利弊。

希望本文能够帮助大家更好地理解和使用Java中的Semaphore

📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

成体系的面试题,无论你是大佬还是小白,都需要一套JAVA体系的面试题,我已经上岸了!你也想上岸吗?

闫工精心准备了程序准备面试?想系统提升技术实力?闫工精心整理了1000+ 套涵盖前端、后端、算法、数据库、操作系统、网络、设计模式等方向的面试真题 + 详细解析,并附赠高频考点总结、简历模板、面经合集等实用资料!

✅ 覆盖大厂高频题型
✅ 按知识点分类,查漏补缺超方便
✅ 持续更新,助你拿下心仪 Offer!

📥免费领取👉 点击这里获取资料

已帮助数千位开发者成功上岸,下一个就是你!✨

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/2 19:56:17

基于Java+SpringBoot+SSM克州旅游网站(源码+LW+调试文档+讲解等)/克州旅游平台/克州旅游信息网/克州旅游门户网站/克州旅游官网/克州旅游服务网站

博主介绍 &#x1f497;博主介绍&#xff1a;✌全栈领域优质创作者&#xff0c;专注于Java、小程序、Python技术领域和计算机毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅&#x1f447;&#x1f3fb; 2025-2026年最新1000个热门Java毕业设计选题…

作者头像 李华
网站建设 2026/5/1 7:55:19

微服务分布式SpringBoot+Vue+Springcloud中药材进存销管理系统

文章目录系统概述技术架构核心功能创新点应用价值主要技术与实现手段系统设计与实现的思路系统设计方法java类核心代码部分展示结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;系统概述 中药材进存销管理系统基于微服务分布式架构&am…

作者头像 李华
网站建设 2026/5/2 17:02:08

微服务分布式SpringBoot+Vue+Springcloud在线投票系统

文章目录微服务分布式在线投票系统摘要主要技术与实现手段系统设计与实现的思路系统设计方法java类核心代码部分展示结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;微服务分布式在线投票系统摘要 基于SpringBoot、Vue和SpringCloud的…

作者头像 李华
网站建设 2026/5/2 12:34:44

智慧社区:居民信息Excel导入数据库

目录 1.技术选型 Apache POI EasyExcel&#xff08;阿里开源流式方案&#xff09; Easy-POI&#xff08;注解驱动方案&#xff09; JXL&#xff08;轻量级旧版方案&#xff09; 前后端协作方案&#xff08;SpreadJS 后端&#xff09; 对比表 2.业务逻辑 3.代码实现 1.…

作者头像 李华
网站建设 2026/5/2 7:14:57

增程系统详细介绍

增程系统&#xff08;Range Extender / 增程式电动车&#xff0c;EREV&#xff09;原理、结构、控制逻辑、优缺点、与其他动力形式对比、以及未来趋势。一、什么是增程系统增程系统 以电机驱动车轮 发动机只负责发电、不直接驱动轮子 本质上是「电动车 随车发电机」。二、系…

作者头像 李华
网站建设 2026/4/23 15:00:54

初始化大模型的不同方式

llama.cpp 「发动机」—— 纯推理库&#xff0c;命令行或 C/C API 调用&#xff0c;什么都要自己拼。 Ollama 「整车」—— 把 llama.cpp 发动机包成 Docker 式服务&#xff0c;一键拉模型、自动启停、REST/OpenAI 兼容&#xff0c;零配置就能用。 维度llama.cppOllama定位底…

作者头像 李华