Java 入门指南:Java 并发编程 —— 同步工具类 Semephore(信号量)

文章目录

    • 同步工具类
    • Semephore
      • 核心功能
        • 限制并发访问量
        • 公平与非公平策略
        • 灵活性与适应性
      • 常用方法
      • 使用示例

同步工具类

JUC(Java.util.concurrent)是 Java 提供的用于并发编程的工具类库,其中包含了一些通信工具类,用于在多个线程之间进行协调和通信,特别是在多线程和网络通信方面。这些工具类提供了丰富的功能,帮助开发者高效地实现复杂的并发控制和网络通信需求。

![[JUC Communication Utilities.png]]

Semephore

Semaphore(信号量)是一种并发控制机制,可用于管理对共享资源的访问以及线程间的同步。Semaphore 通过控制许可数量(permits),实现了对并发线程数的精细管理,有效避免了资源竞争和过载问题,能显著提升系统吞吐量和响应速度。通常被用于限制对某个资源或资源池的并发访问数量。

核心功能

Semaphore 维护了一个计数器,该计数器表示可用的许可数

限制并发访问量

线程可以通过 acquire() 方法获取一个许可,如果计数器大于0,则线程获取许可并将计数器减1;如果计数器为0,则线程将被阻塞,直到有一个许可可用。

当线程使用完资源后,可以通过 release() 方法释放许可,将计数器增加,以供其他线程获取。

Semaphore 常用于限制并发访问资源的线程数。可以通过构造函数指定初始许可数,或不指定时默认为1。当初始许可数小于线程数时,只能有部分线程能够同时访问资源,其他线程需要等待。

公平与非公平策略

Semaphore 支持公平(Fair)和非公平(Nonfair)两种策略,还可以用于实现线程间的协调和通信。

  • 公平模式下,线程将按照请求许可证的顺序获得许可证,即先请求的线程将先得到许可证。

  • 非公平模式下,线程则可能不按照请求的顺序获得许可证,这可能会导致某些线程饥饿。

例如,可以使用 Semaphore 确保一组线程中的某些线程先执行,然后再由 Semaphore 释放许可,使得其他线程可以执行。

需要注意的是,Semaphore 只是对资源访问进行计数和控制,并不保证线程执行顺序,也不提供锁的锁定和解锁操作。在使用 Semaphore 时,需要遵循正确的获取和释放许可的顺序,以避免死锁或资源泄漏等问题。

灵活性与适应性

Semaphore 的灵活性在于它可以动态地调整许可数量,以适应系统负载的变化。例如,在资源池管理中,可以根据系统的实际使用情况,动态地增加或减少许可数量,以提高资源利用率和系统性能。

常用方法

Semaphore 提供了几个关键的方法来控制许可证的获取和释放:

  • acquire():获取一个许可证。如果没有可用的许可证,则当前线程将被阻塞,直到有许可证可用。

  • acquire(int permits):一次性获取指定数量的许可证。如果没有足够数量的许可证可用,则当前线程将被阻塞。

  • release():释放一个许可证。这将使 Semaphore 的可用许可证数量加一。

  • release(int permits):释放指定数量的许可证。

  • tryAcquire()tryAcquire(int permits, long timeout, TimeUnit unit):尝试获取许可证,如果在指定时间内无法获取到许可证,则返回 false。这些方法不会使线程阻塞。

使用示例

以下是一个简单的示例代码,演示了如何使用 Semaphore 来限制对一组资源的并发访问:

import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.Semaphore;  public class SemaphoreExample {  // 创建一个Semaphore,初始许可为3,表示资源池中最多有3个资源可用  private static final Semaphore semaphore = new Semaphore(3);  public static void main(String[] args) {  // 创建一个固定大小的线程池来模拟客户端请求  ExecutorService executor = Executors.newFixedThreadPool(5);  // 提交10个任务到线程池,每个任务代表一个客户端请求  for (int i = 0; i < 10; i++) {  executor.submit(() -> {  try {  // 线程尝试获取许可  semaphore.acquire();  System.out.println("线程" + Thread.currentThread().getName() + "获取到资源,开始处理...");  // 模拟资源处理时间  Thread.sleep((long) (Math.random() * 1000));  System.out.println("线程" + Thread.currentThread().getName() + "处理完毕,释放资源...");  // 线程释放许可  semaphore.release();  } catch (InterruptedException e) {  e.printStackTrace();  }  });  }  // 关闭线程池  executor.shutdown();  }  
}

在这个示例中,我们创建了一个 Semaphore 实例,初始许可设置为3,这意味着最多只能有3个线程同时访问资源。然后,我们创建了一个固定大小为5的线程池来模拟客户端请求,并提交了10个任务到线程池。每个任务都尝试获取 Semaphore 的许可来模拟资源的访问。从输出结果中可以看到,尽管线程池的大小为5,但 Semaphore 确保了同时访问资源的线程数不超过3个。

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

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

相关文章

C语言-综合案例:通讯录

传送门&#xff1a;C语言-第九章-加餐&#xff1a;文件位置指示器与二进制读写 目录 第一节&#xff1a;思路整理 第二节&#xff1a;代码编写 2-1.通讯录初始化 2-2.功能选择 2-3.增加 和 扩容 2-4.查看 2-5.查找 2-6.删除 2-7.修改 2-8.退出 第三节&#xff1a;测试 下期…

【单片机开发】单片机常用开发工具

【前言】 在嵌入式系统领域&#xff0c;单片机&#xff08;Microcontroller, MCU&#xff09;作为核心组件&#xff0c;广泛应用于智能家居、工业控制、汽车电子等众多领域。而单片机开发工具&#xff0c;则是开发者们实现创意、解决问题的重要助手。本文主要讲述目前主流的单…

港科夜闻 | 叶玉如校长出席2024科技+新质生产力高峰论坛发表专题演讲,贡献国家科技强国战略...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、叶玉如校长出席“2024科技新质生产力高峰论坛”&#xff0c;做了题为“三个创新&#xff1a;培育和发展新质生产力、贡献国家科技强国战略”的主题演讲。该论坛于9月2日在香港召开。论坛围绕夯实基础科研、推动源头创新、…

axure判断

在auxre中我们也可以实现判断的功能&#xff0c;当目标等于什么内容时则执行下方的功能。 一、判断输入框中是否有值 画布添加一个输入框、一个文本标签删除其中内容&#xff0c;添加一个按钮&#xff0c;输入框命名为【文本显示】文本标签命名为【提示】 给按钮新增一个交互…

单向链表概述

文章目录 &#x1f34a;自我介绍&#x1f34a;单向链表概述数据域和指针域数据类型设计 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以&#xff1a;点赞关注评论收藏&#xff08;一键四连&#xff09;哦~ &#x1f34a;自我介绍 Hello,大家好&#xff0c;我是小珑也要…

(计算机网络)应用层

1.为什么需要应用层 应用层提供使用tcp&#xff0c;udp使用的方式 协议就是制定的规则 2.域名服务器概述 域名是唯一的 新增域名&#xff0c;大家都要修改这个文本文件&#xff0c;所以要进行集中管理这个文本文件&#xff0c;而不是使用本地的hosts文件 hosts文件在Windows系统…

Java | Leetcode Java题解之第397题整数替换

题目&#xff1a; 题解&#xff1a; class Solution {public int integerReplacement(int n) {int ans 0;while (n ! 1) {if (n % 2 0) {ans;n / 2;} else if (n % 4 1) {ans 2;n / 2;} else {if (n 3) {ans 2;n 1;} else {ans 2;n n / 2 1;}}}return ans;} }

部署定时任务每2天清理一次表

1、创建存储过程 create or replace procedure truct authid current_user ---使用“authid Current_user”将存储过程转化为调用者权限 as begin execute immediate truncate table rep.tmp_s_st_busi_send_arc; end; / 2、创建定时任务 begin dbms_scheduler.create…

机器学习中的聚类艺术:探索数据的隐秘之美

一 什么是聚类 聚类是一种经典的无监督学习方法&#xff0c;无监督学习的目标是通过对无标记训练样本的学习&#xff0c;发掘和揭示数据集本身潜在的结构与规律&#xff0c;即不依赖于训练数据集的类标记信息。聚类则是试图将数据集的样本划分为若干个互不相交的类簇&#xff…

【人工智能学习笔记】4_3 深度学习基础之循环神经网络

循环神经网络(Recurrent Neural Network, RNN) 是一类以序列(sequence)数据为输入,在序列的演进方向进行递归(recursion)且所有节点(循环单元)按链式连接的递归神经网络(recursive neural network),循环神经网络具有短期记忆能力 RNN核心思想 RNN的结构 一个典型…

【JS逆向学习】快乐学堂登陆接口(自定义DES加密、ddddocr验证码识别)

逆向目标 网址&#xff1a;https://www.91118.com/Passport/Account/Login接口&#xff1a;https://www.91118.com/passport/Account/LoginPost参数&#xff1a; passr 逆向过程 输入手机号、密码、验证码 点击登陆&#xff0c;多试几次&#xff0c;然后观察并比较不通请求…

鸿蒙界面开发——组件(7):组件导航 页面路由

组件导航 (Navigation)(推荐) Navigation() Navigation(pathInfos: NavPathStack)Navigation是路由容器组件&#xff0c;一般作为首页的根容器&#xff0c;包括单栏(Stack)、分栏(Split)和自适应(Auto)三种显示模式。Navigation组件适用于模块内和跨模块的路由切换&#xff0c…

ApacheKafka中的设计

文章目录 1、介绍1_Kafka&MQ场景2_Kafka 架构剖析3_分区&日志4_生产者&消费者组5_核心概念总结6_顺写&mmap7_Kafka的数据存储形式 2、Kafka的数据同步机制1_高水位&#xff08;High Watermark&#xff09;2_LEO3_高水位更新机制4_副本同步机制解析5_消息丢失问…

ollama 本地部署

ollama 本地模型部署 下载安装: [link](https://ollama.com/download)下载说明 部署使用在终端查看ollama是否安装完成终端查看ollama 命令说明查看当前支持下载的模型启动对话模式默认情况下&#xff0c;ollama启动了server 的api访问功能 外部 api访问使用postman网页版本for…

【MATLAB】模拟退火算法

模拟退火算法的MATLAB实现 模拟退火算法简介模拟退火算法应用实例关于计算结果 模拟退火算法简介 1982年&#xff0c;Kirkpatrick 将退火思想引入组合优化领域&#xff0c;提出了一种能够有效解决大规模组合优化问题的算法&#xff0c;尤其对 NP 完全问题表现出显著优势。模拟…

电商平台如何实现自动监控订单签收状态,加快资金划拨进程?

资金划拨作为交易流程的核心环节之一&#xff0c;直接关系到商家资金回笼的速度、消费者购物体验的满意度以及平台自身的信誉与稳定性。 区别于自营电商&#xff0c;电商平台入驻了许多第三方商家&#xff0c;为了保障交易安全和控制风险&#xff0c;在交易未完成之前&#xff…

超声波测距模块HC-SR04(基于STM32F103C8T6HAL库)

超声波测距模块参考资料 1.电路连接及引脚配置 触发信号PA3只需要输出10us的高电平&#xff0c;所以直接设置成 普通的GPIO端口即可&#xff1b;回响信号使用外部中断&#xff0c;上升沿信号产生外部中断&#xff0c;打开定时器&#xff0c;下降沿再产生一次中断&#xff0c;读…

数据丢失?别慌!EasyRecovery带你轻松寻回!

&#x1f31f; 意外总在不经意间降临 &#x1f31f; 亲爱的小伙伴们&#xff0c;你是否有过这样的经历&#xff1a;正专心致志地处理着电脑文件&#xff0c;突然一次误操作&#xff0c;重要的资料就这样不见了&#xff0c;那种心如刀绞的感觉瞬间涌上心头。&#x1f616; 使用…

MySQL事务【后端 13】

MySQL事务 在数据库管理系统中&#xff0c;事务&#xff08;Transaction&#xff09;是一个非常重要的概念&#xff0c;它确保了数据库操作的完整性和一致性。MySQL作为一种流行的关系型数据库管理系统&#xff0c;自然也支持事务处理。本文将深入探讨MySQL事务的基本概念、特性…

StorageSync数据缓存API

uni.setStorageSyncs参数:将 data 存储在本地缓存中指定的 key 中&#xff0c;会覆盖掉原来该 key 对应的内容&#xff0c;这是一个同步接口。 uni.setStorageSync函数里面写两个参数,分别是key和值,两个参数名称可以随便取,如果有同名的key,那么后面key的值会覆盖掉前面key的值…