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

news2024/11/8 20:54:55

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

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

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信号量,初始化许可大小为3
        final  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对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场合。

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.coloradmin.cn/o/2161236.html

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

相关文章

程序员修炼之道 13:务实的项目

不记录&#xff0c;等于没读。 这里是我阅读《程序员修炼之道》这本书的记录和思考。 务实的团队 一个项目不只你一个人&#xff0c;就需要建立一些基本规则&#xff0c;并依次将项目的各部分分配出去。 程序员有点像猫&#xff1a;聪明、意志坚强、固执己见、独立、并且经常…

3. 函数

函数是 JavaScript 编程中最重要的工具之一。用一个值封装一段程序的概念有很多用途。它为我们提供了一种结构化大型程序的方法&#xff0c;可以减少重复&#xff0c;将名称与子程序关联起来&#xff0c;并将这些子程序相互隔离。 函数最明显的应用是定义新的词汇。在散文中创造…

一款前后端分离CRM客户关系管理系统,支持客户,商机,线索,合同,发票,审核,商品等功能(附源码)

前言 在当今竞争激烈的商业环境中&#xff0c;企业面临着各种挑战&#xff0c;其中包括如何更有效地管理和跟进潜在客户以提高销售业绩。传统的客户管理方式往往效率低下&#xff0c;无法实时更新客户-信息&#xff0c;导致销售机会流失。因此&#xff0c;市场上急需一款能够简…

计算机毕设选题推荐-基于python的电子健康信息分析系统【源码+文档+调试】

精彩专栏推荐订阅&#xff1a;在下方主页&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f496;&#x1f525;作者主页&#xff1a;计算机毕设木哥&#x1f525; &#x1f496; 文章目录 一、电子健康信息…

【解决虚拟机NAT联网】收藏这份教程就不用再辛苦找了

网上的教程一大堆&#xff0c;看的云里雾里&#xff0c;对于一个小白来说这里看懂了&#xff0c;下一步又看不懂了&#xff0c;一模一样的去设置也不一定成功。 解决办法01 恢复默认设置&#xff1a; 首先公布一个最基础的最直接最有效的恢复网络的办法&#xff1a; 关闭虚拟…

Python字典进阶:setdefault技巧让你的代码更优雅,用setdefault优化你的Python数据处理流程

推荐阅读&#xff1a; 数据科学的秘密武器&#xff1a;defaultdict——Python字典的自动化填充神器&#xff0c;让数据结构更灵活 一、什么是setdefault Python中的setdefault方法是字典&#xff08;dict&#xff09;类型的一个非常实用的方法&#xff0c;它允许开发者在尝试…

Invalid Executable The executable contains bitcode

Invalid Executable The executable contains bitcode xcode世界xcode16后&#xff0c;打包上传testflight时三方库报错&#xff1a;Invalid Executable - The executable ***.app/Frameworks/xxx.framework/xxx contains bitcode. 解决方案&#xff1a; 执行一下指令删除该f…

创建单链表

一、完成单链表操作&#xff0c;要求节点构造类型。 1、建立学生结构体&#xff08;学号&#xff0c;姓名&#xff0c;成绩&#xff09; 2、循环调用头插法创建整表 3、遍历单链表 4、任意位置插入一个完整的学生信息 5、任意位置删除一个学生。 6、单链表逆置 7、单链表按照学…

Vulnhub:Fowsniff 1

靶机下载地址 信息收集 主机发现 nmap 192.168.31.0/24 -Pn -T4 靶机ip&#xff1a;192.168.31.134 端口扫描 nmap 192.168.31.134 -A -p- -T4 开放端口22(ssh)、80(http)&#xff0c;和两个明文传输的邮件端口110(pop3)、143(imap)。 HTTP 访问http://192.168.31.134。…

云栖实录 | 阿里云 OpenLake 解决方案重磅发布:多模态数据统一纳管、引擎平权联合计算、数据共享统一读写

新一轮人工智能浪潮正在重塑世界&#xff0c;以生成式 AI 为代表的技术快速应用&#xff0c;推动了数据与智能的深化融合&#xff0c;同时也给数据基础设施带来了全新的变革与挑战。面向 AI 时代的数据基础设施如何构建&#xff1f;底层数据平台架构在 AI 时代如何演进&#xf…

word怎么加密?掌握这4种加密技巧,保护你的文件安全!

数字化办公社会&#xff0c;文档安全显得尤为重要。 无论是商业机密、个人隐私还是学术成果&#xff0c;我们都希望它们能在传递过程中得到妥善保护。 Word文档作为最常用的文档处理工具&#xff0c;用户有效保障文档的安全性是维护企业信息安全的重要渠道。 Word文档的加密是…

纯血鸿蒙APP开发启动页面无法全屏解决办法

先来看问题&#xff1a; 本身APP并不需要全屏&#xff0c;但是启动页这种特殊页面确实需要忽略页面上下的安全边界区域&#xff0c;解决办法也很简单&#xff0c;直接上代码&#xff1a; Image($r(app.media.launch_icon)) .width(100%) .height(100%) .expandSafeArea([SafeA…

mysql 重置密码

1.关闭mysql 服务 systemctl stop mysql.serivce 2.修改mysql的配置文件 /etc/my.cnf vi /etc/my.cnf#添加跳过登陆验证配置 skip-grant-tables 3.启动mysql systemctl start mysql.serivce 4.登陆mysql #进入到mysql的安装路径 cd /usr/local/mysql/mysql8.0/bin/ #登陆 …

SpringBoot文档管理系统:性能优化

第3章 系统分析 3.1 需求分析 在线文档管理系统主要是为了提高工作人员的工作效率和更方便快捷的满足员工&#xff0c;更好存储所有数据信息及快速方便的检索功能&#xff0c;对系统的各个模块是通过许多今天的发达系统做出合理的分析来确定考虑员工的可操作性&#xff0c;遵循…

windows桌面管理软件推荐:一键整理桌面!美化电脑桌面小助手!

windows桌面管理软件推荐来咯&#xff01;在繁忙的工作和生活中&#xff0c;一个整洁、有序的电脑桌面不仅能提升工作效率&#xff0c;还能带来愉悦的视觉体验。然而&#xff0c;随着文件的增多&#xff0c;桌面往往变得杂乱无章。幸运的是&#xff0c;市面上有许多优秀的Windo…

CDGA|解锁数据价值:基础数据治理的至关重要性

在当今这个数据驱动的时代&#xff0c;数据已成为企业最宝贵的资产之一&#xff0c;其蕴含的价值远超传统资源。然而&#xff0c;要真正解锁数据的潜在价值&#xff0c;并非简单收集与存储即可达成&#xff0c;而是需要一套科学、系统的数据治理体系作为支撑。本文旨在探讨基础…

在idea里运行swing程序正常,但是在外部运行jar包却报错,可能是jdk版本问题

在idea里运行swing程序异常&#xff0c;报Caused by: java.awt.HeadlessException错误 System.setProperty("java.awt.headless","false");加上这句话

Spring Data Rest 远程命令执行命令(CVE-2017-8046)

&#xff08;1&#xff09;访问 http://your-ip:8080/customers/1&#xff0c;然后抓取数据包&#xff0c;使用PATCH请求来修改 PATCH /customers/1 HTTP/1.1 Host: Accept-Encoding: gzip, deflate Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (compatible; MS…

Solidity——抽象合约和接口详解

&#x1f680;本系列文章为个人学习笔记&#xff0c;目的是巩固知识并记录我的学习过程及理解。文笔和排版可能拙劣&#xff0c;望见谅。 Solidity中的抽象合约和接口详解 目录 什么是抽象合约&#xff1f;抽象合约的语法接口&#xff08;Interface&#xff09;的定义接口的语…

Gooxi AMD Milan平台4U8卡AI服务器,兼具性能与成本的完美之选

近日&#xff0c;为了帮助企业从容应对当下多样化场景的算力挑战&#xff0c;Gooxi发布了基于AMD Milan平台的全新4U8卡AI服务器&#xff0c;在性能以及成本实现了完美平衡&#xff0c;并且在灵活性、稳定性、能耗方面实现了持续升级。 Gooxi AMD Milan平台4U8卡AI服务器是一款…