《Java并发编程实战》课程笔记(九)

news2024/11/16 19:26:20

Semaphore:如何快速实现一个限流器?

信号量模型

  • 信号量模型还是很简单的,可以简单概括为:一个计数器,一个等待队列,三个方法。
    在这里插入图片描述
  • 在信号量模型里,计数器和等待队列对外是透明的,所以只能通过信号量模型提供的三个方法来访问它们,这三个方法分别是:init()、down() 和 up()。
    • init():设置计数器的初始值。
    • down():计数器的值减 1;如果此时计数器的值小于 0,则当前线程将被阻塞,否则当前线程可以继续执行。
    • up():计数器的值加 1;如果此时计数器的值小于或者等于 0,则唤醒等待队列中的一个线程,并将其从等待队列中移除。
    • 在 Java SDK 里面,信号量模型是由 java.util.concurrent.Semaphore 实现的,Semaphore 这个类能够保证这三个方法都是原子操作。
    • 在 Java SDK 并发包里,down() 和 up() 对应的则是 acquire() 和 release()。

如何使用信号量

快速实现一个限流器

  • 实现一个互斥锁,仅仅是 Semaphore 的部分功能,Semaphore 还有⼀个功能是 Lock 不容易实现的,那就是:Semaphore 可以允许多个线程访问一个临界区
    • 比较常见的需求就是我们工作中遇到的各种池化资源,例如连接池、对象池、线程池等等。
    • 其中,数据库连接池,在同一时刻,一定是允许多个线程同时使用连接池的,当然,每个连接在被释放前,是不允许其他线程使用的。
  • 所谓对象池,指的是一次性创建出 N 个对象,之后所有的线程重复利用这 N 个对象,当然对象在被释放前,也是不允许其他线程使用的。
    • 对象池,可以用 List 保存实例对象,这个很简单。
    • 但关键是限流器的设计,这里的限流,指的是不允许多于 N 个线程同时进入临界区。
    • 那如何快速实现⼀个这样的限流器呢?如果我们把计数器的值设置成对象池里对象的个数 N,就能完美解决对象池的限流问题了。
      import java.util.List;
      import java.util.Vector;
      import java.util.concurrent.Semaphore;
      import java.util.function.Function;
      
      public class ObjPool<T, R> {
          final List<T> pool;
          // ⽤信号量实现限流器
          final Semaphore semaphore;
          // 构造函数
          ObjPool(int size, T t) {
              pool = new Vector<T>(){};
              for (int i = 0; i < size; i++) {
                  pool.add(t);
              }
              semaphore = new Semaphore(size);
          }
      
          // 利⽤对象池的对象,调⽤ func
          // function 的作用是转换,将一个值转为另外一个值
          R exec(Function<T, R> function) throws InterruptedException {
              T t = null;
              semaphore.acquire();
              try {
                  t = pool.remove(0);
                  return function.apply(t);
              } finally {
                  pool.add(t);
                  semaphore.release();
              }
          }
      
          public static void main(String[] args) throws InterruptedException {
              // 创建对象池
              ObjPool<Long, String> objPool = new ObjPool<Long, String>(10, 2L);
              // 通过对象池获取 t,之后执⾏
              objPool.exec(t -> {
                  System.out.println(t);
                  return t.toString();
              });
          }
      }
      
    • 我们用一个 List来保存对象实例,用 Semaphore 实现限流器。
    • 关键的代码是 ObjPool 里面的 exec() 方法,这个方法里面实现了限流的功能。
      • 在这个方法里面,我们首先调用 acquire() 方法(与之匹配的是在 finally 里面调用 release() 方法),假设对象池的大小是 10,信号量的计数器初始化为 10,那么前 10 个线程调用 acquire() 方法,都能继续执行,而其他线程则会阻塞在 acquire() 方法上。
      • 我们为每个线程分配了一个对象 t(这个分配工作是通过 pool.remove(0) 实现的),分配完之后会执行一个回调函数 func,而函数的参数正是前面分配的对象 t ;执行完回调函数之后,它们就会释放对象(这个释放工作是通过 pool.add(t) 实现的),同时调用 release() 方法来更新信号量的计数器。
      • 如果此时信号量里计数器的值小于等于 0,那么说明有线程在等待,此时会自动唤醒等待的线程。

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

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

相关文章

chatgpt赋能python:Python图片大小设置的SEO指南

Python 图片大小设置的SEO指南 在网站设计和开发中&#xff0c;图片大小通常是一个重要的问题。合适的图片大小可以极大地影响用户体验和搜索引擎优化&#xff08;SEO&#xff09;结果。Python是一种广泛使用的编程语言&#xff0c;可以用来控制和设置图片大小。在本文中&…

BUUCTF MD5

密文&#xff1a; e00cf25ad42683b3df678c61f42c6bda 简述&#xff1a; 一般MD5值是32位由数字“0-9”和字母“a-f”所组成的字符串&#xff0c;字母大小写统一&#xff1b;如果出现这个范围以外的字符说明这可能是个错误的md5值&#xff0c;就没必要再拿去解密了。 特征&…

SQL-DDL操作数据库、表

SQL-DDL操作数据库、表 1 DDL:操作数据库 1.1 查询数据库 查询所有的数据库 SHOW DATABASES; show databases;1.2 创建数据库 创建数据库 CREATE DATABASE 数据库名称; create database 数据库名称;创建数据库(判断&#xff0c;如果不存在则创建) CREATE DATABASE IF NOT…

SyntaxError:Unexpected end of JSON input while parsing near xxxxx 报错及解决

环境&#xff1a;Node 12.21.0、npm 6.14.11 &#xff08;其他版本也会出现这样的问题&#xff09; 找到报错日志并进行查看&#xff1a; less /Users/roc/.npm/_logs/2023-06-05T02_23_51_747Z-debug.log报错信息如下&#xff1a; 19067 verbose stack SyntaxError: Unexp…

【遇到的问题】JAVA应用程序处于安全原因被阻止。

遇到的问题&#xff1a; 直入正题&#xff0c;远程服务器用JAVA连接KVM报以下错(如图)。 应用程序处于安全原因被阻止 无法验证证书 将不执行该应用程序 名称&#xff1a;Java viewer 发行者&#xff1a;ATEN 位置&#xff1a;https://192.168.210:443 原因&#xff1a; 通过…

vue3实现高德地图多点标注(so easy)

vue3实现高德地图多点标注&#xff08;so easy&#xff09; 前言思路清晰&#xff0c;抽丝剥茧必要的准备工作最简单的部分处理数据之前&#xff08;最关键的思路&#xff09;效果完整代码 前言 非常感谢你能打开这篇博客&#xff0c;我想你一定是遇到了地图多点标注有关的问题…

采购管理系统对企业有什么作用?原来用零代码搭建如此便捷

什么是采购管理系统&#xff1f; 采购管理系统是一种企业内部管理软件&#xff0c;用于协调和管理企业的采购过程。它涵盖了采购计划、询价、比价、采购订单、采购合同、采购收货、发票等一系列采购环节&#xff0c;以及与供应商的信息和交流。其主要目的是&#xff1a;优化采…

M12圆形连接器公母对接带线3PIN4PIN

随着工业自动化的发展&#xff0c;M12圆形连接器公母对接带线3PIN4PIN作为一种重要的连接器件&#xff0c;被广泛应用于各种工业设备中。本文将详细介绍M12连接器的特点以及应用场景&#xff0c;为大家解答M12连接器的相关问题。 M12连接器主要由连接器头、插座和电缆组成&…

【Web网站服务】Nginx Rewrite重写模块

Nginx Rewrite 一、常用的Nginx 正则表达式二、location 匹配的范围2.1location实验 三、rewrite模块3.1rewrite跳转3.2rewrite执行顺3.3flag标记说明3.4rewrite中常用的全局变量3.5rewrite实验3.5.1 基于域名的跳转3.5.2基于客户端IP访问跳转3.5.3基于旧域名跳转到新域名后面加…

三、HAL_无源蜂鸣器的驱动

1、开发环境 (1)KeilMDK&#xff1a;V5.38.0.0 (2)STM32CubeMX&#xff1a;V6.8.1 (3)MCU&#xff1a;STM32F407ZGT6 2、无源蜂鸣器简介 无源蜂鸣器内部没有振荡源&#xff0c;需要采用一定频率的方波才能驱动发声。详情参开以下文章。 八、51单片机之蜂鸣器_51蜂鸣器_朱嘉…

DINO代码学习笔记(三)

DINO代码学习笔记&#xff08;一&#xff09;中已经将输入transformer之前的参数处理给捋了一遍 DINO代码学习笔记&#xff08;二&#xff09;中将encoder部分给捋了一遍 本篇进入decoder&#xff0c;这里先对encoder做一些假设&#xff0c;基于DINO代码学习笔记&#xff08;…

使用Harbor 和 Kraken 优化镜像拉取速

一、P2P镜像分发简述 随着云原生架构被越来越多的企业接受&#xff0c;企业应用中容器集群的规模也越来越大。当容器集群达到一定的规模且单容器应用副本数达到一定级别时&#xff0c;集群中容器镜像的分发将面临挑战。   P2P&#xff08;Peer-to-Peer&#xff0c;点对点&am…

股票策略社群实盘展示

量化策略开发&#xff0c;高质量社群&#xff0c;交易思路分享等相关内容 大家好&#xff0c;我是Le Chiffre 从今年1月份开始&#xff0c;我们开始了松鼠股票策略社群&#xff0c;历经5个月&#xff0c;发布了5个策略。其中有2个多因子&#xff0c;2个etf&#xff0c;1个网格…

一款企业级的供应链采购系统,已开源

介绍 基于pig微服务架构打造 供应链系统&#xff0c;采购配送系统。为客户提供仓储管理、订单管理、打单、货源采购、分拣、配送等系统功能。 软件架构 采用 J2EE 技术体系&#xff0c;基于Spring Cloud微服务框架进行封装&#xff0c;平台设计灵活可扩展、可移植、可应对高…

Java使用EasyCode自动生成代码工具分享

此为内容创作模板&#xff0c;在发布之前请将不必要的内容删除 做Java的项目开发&#xff0c;会使用各种代码自动生成工具&#xff0c;今天就来介绍一款EasyCode插件&#xff0c;废话不多说了&#xff0c;看看怎么安装和使用。 一、EasyCode插件 EasyCode的安装 在Idea的Sett…

在云服务器上安装MySQL (MariaDB) 数据库并与Python连接和互动

诸神缄默不语-个人CSDN博文目录 本文介绍如何在云服务器&#xff08;CentOS&#xff09;上安装MySQL数据库&#xff08;其实是MariaDB数据库&#xff0c;但是当成MySQL用也没什么问题&#xff09;&#xff0c;并用pymysql与原生Python代码进行互动&#xff0c;或用Flask-SQLAl…

SpringSecurityOAuth已停更,来看一看进化版本Spring Authorization Server

Spring Authorization Server是Spring Security OAuth的进化版本&#xff0c;Spring Security OAuth官方已经宣布“End of Life”了。Spring Security OAuth使用的是OAuth2.0标准而Spring Authorization Serve引入了对OAuth 2.1和OpenID Connect 1.0规范的支持&#xff0c;并提…

开源赋能 普惠未来|OpenHarmony诚邀您参与2023开放原子全球开源峰会

OpenHarmony面向万物智联&#xff0c;秉持“生态统一、开放共赢”的理念&#xff0c;围绕“架构解耦、弹性部署”“自由流转、智慧协同”和“极简开发、一致体验”三大架构特征&#xff0c;构建分布式全场景协同的开源操作系统基座与生态系统。面向全场景、全连接、全智能时代&…

项目管理工具最新排名出炉,哪款最适合您?

项目管理工具当下已经成为项目团队的重要榜首&#xff0c;一款合适好用的项目管理工具可以帮助处理很多机械化工作&#xff0c;将管理者更多精力投入到更有价值的工作中&#xff0c;还可以帮助团队组织和计划项目&#xff0c;跟踪进度&#xff0c;处理预算和协作。 该如何挑选帮…

程序员必须掌握的消息中间件-RocketMQ

设计(design) 1 消息存储 消息存储是RocketMQ中最为复杂和最为重要的一部分&#xff0c;本节将分别从RocketMQ的消息存储整体架构、PageCache与Mmap内存映射以及RocketMQ中两种不同的刷盘方式三方面来分别展开叙述。 1.1 消息存储整体架构 消息存储架构图中主要有下面三个跟消息…