Java面试篇基础部分-Semaphore及其用法详解

embedded/2024/9/25 6:24:18/

  Semaphore 是一种基于计数的信号量,在定义信号量对象的时候可以设置一个阈值,然后基于这个阈值,多线程可以竞争访问信号量,线程竞争到许可的信号之后,开始执行具体的业务逻辑,业务逻辑在执行完成之后释放这个许可信号。

在这里插入图片描述
  如果许可信号竞争队列超过阈值,新加入的申请信号许可的线程就会被阻塞,知道有其他许可信号被释放。使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数。

java">import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;public class SemaphoreTest {public static void main(String[] args) {ExecutorService service = Executors.newCachedThreadPool();//创建Semaphore信号量,初始化许可大小为3final  Semaphore sp = new Semaphore(3);for(int i=0;i<10;i++){try {Thread.sleep(100);} catch (InterruptedException e2) {e2.printStackTrace();}Runnable runnable = new Runnable(){public void run(){try {//请求获得许可,如果有可获得的许可则继续往下执行,//许可数减1。否则进入阻塞状态sp.acquire();} catch (InterruptedException e1) {e1.printStackTrace();}System.out.println("线程" + Thread.currentThread().getName() + "进入,当前已有" + (3-sp.availablePermits()) + "个并发");try {Thread.sleep((long)(Math.random()*10000));} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程" + Thread.currentThread().getName() + "即将离开");                    sp.release();//释放许可,许可数加1//下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元System.out.println("线程" + Thread.currentThread().getName() + "已离开,当前已有" + (3-sp.availablePermits()) + "个并发");                    }};service.execute(runnable);            }}}

  Semaphore 对于锁的申请与释放和ReentrantLock是类似的,通过acquire()方法和release()方法来获取和释放许可信号资源。

  Semaphore.acquire()方法与
ReentrantLock.lockInterruptibly()方法的效果是一样的,为可响应中断的锁。也就是说在等待获取许可信号的过程中可以被Thread.interrupt()方法中断而取消对许可信号的申请操作。

  除此之外,Semaphore也实现了可轮询的锁请求、定时锁的等功能,以及公平与非公平锁的定义在构造函数中设定

  Semaphore锁的释放操作也需要手动进行释放,为此为了避免线程因为异常没有正常释放锁,释放锁的操作必须在finally代码块中完成。

  Semaphore也可以用于实现一些对象池、资源池的构建,例如静态全局对象池、数据库连接池等等。

  单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场合。

java">import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class LockTest {public static void main(String[] args) {final Business business = new Business();ExecutorService executor =  Executors.newFixedThreadPool(3);for(int i=0;i<3;i++){executor.execute(new Runnable(){public void run(){business.service();}});}executor.shutdown();}private static class Business{private int count;Lock lock = new ReentrantLock();Semaphore sp = new Semaphore(1);public void service() {//lock.lock();try {//当前线程使用count变量的时候将其锁住,不允许其他线程访问sp.acquire(); } catch (InterruptedException e1) {e1.printStackTrace();}try {count++;try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(count);} catch (RuntimeException e) {e.printStackTrace();}finally{//lock.unlock();sp.release();  //释放锁}}}        }

http://www.ppmy.cn/embedded/116485.html

相关文章

6.C++面向对象2(默认成员函数,构造函数,析构函数详解)

⭐本篇为C学习第6章&#xff0c;主要了解默认成员函数&#xff0c;构造函数&#xff0c;析构函数 ⭐本人Gitee C代码仓库&#xff1a;yzc的c学习: 小川c的学习记录 - Gitee.com 目录 一. 类的6个默认成员函数 二. 构造函数 三.析构函数 四 多个对象调用构造函数和析构函数的…

ubuntu挂载磁盘或U盘

方法 在Ubuntu中&#xff0c;使用命令行读取U盘通常涉及到以下几个步骤&#xff1a;插入U盘、查找设备名称、挂载U盘以及访问文件。以下是详细步骤&#xff1a; 1. 插入U盘 将U盘插入计算机的USB端口。 2. 查找设备名称 你可以使用lsblk或dmesg命令来查找新插入的U盘设备名…

游戏开发2025年最新版——八股文面试题(unity,虚幻,cocos都适用)

1.静态合批与动态合批的原理是什么&#xff1f;有什么限制条件&#xff1f;为什么&#xff1f;对CPU和GPU产生的影响分别是什么&#xff1f; 原理&#xff1a;Unity运行时可以将一些物体进行合并&#xff0c;从而用一个描绘调用来渲染他们&#xff0c;就是一个drawcall批次。 限…

Linux 基本指令的学习

01. ls 指令 语法 &#xff1a; ls [ 选项 ][ 目录或文件 ] 功能 &#xff1a;对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。对于文件&#xff0c;将列出文件名以及其他信息。 常用选项&#xff1a; -a 列出目录下的所有文件&#xff0c;包括以 . 开头的隐含…

从 Oracle 集群到单节点环境(详细记录一次数据迁移过程)之一:生产环境与目标服务器详情

从 Oracle 集群到单节点环境&#xff08;详细记录一次数据迁移过程&#xff09;之一&#xff1a;生产环境与目标服务器详情 目录 从 Oracle 集群到单节点环境&#xff08;详细记录一次数据迁移过程&#xff09;之一&#xff1a;生产环境与目标服务器详情一、操作系统环境二、Or…

springboot整合openfeign

文章目录 准备一、引入必要依赖二、写一个feign client并暴露到注册中心2.1 client2.2 开启Feign客户端功能 三、别的服务引入IProductClient并调用方法3.1 建一个order-service&#xff0c;引入IProductClient所在模块3.2 注入IProductClient&#xff0c;并调用方法 四、启动服…

【计算机网络 - 基础问题】每日 3 题(二十)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏&…

01_WebRtc_一对一视频通话

文章目录 通话网页的设计客户端实现Web的API 服务端实现 2024-9-20 很久没有写博客啦&#xff0c;回顾总结这段时间的成果&#xff0c; 写下博客放松下&#xff08;开始偷懒啦&#xff09;主要内容&#xff1a;实现网页&#xff08;html&#xff09;打开摄像头并显示到页面需要…