使用Semaphore做并发个数控制

2024-09-01 00:58

本文主要是介绍使用Semaphore做并发个数控制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

Semaphore可以控制某个资源可被同时访问的个数,acquire()获取一个许可,如果没有就等待,而release()释放一个许可。比如在Windows下可以设置共享文件的最大客户端访问个数。

另外重入锁ReentrantLock也可以实现该功能,但实现上代码也要复杂些。

 

SemaPhore,一个信号量对象,可以定义信号量的个数,通过该信号量控制线程同步的数量。例如我们只允许同步三个线程进入共享资源,其它线程都阻塞。

好比,厕所有三个坑,十个人进去,每次只能进去三个。采用信号灯来实现。

其优势为可以被其它线程唤醒,如果使用互斥锁,那么一旦出现异常,该锁将不会释放,该锁只能由自己释放。比如:一个人上厕所,如果采用互斥锁,那么当该人晕倒在厕所时,这个厕所就不能被使用了。如果使用信号灯互斥,那么能够找到物业人员打开厕所,救人并接着使用。

 

Java代码   收藏代码
  1. //构造方法摘要  
  2. Semaphore(int permits)   
  3.           //创建具有给定的许可数和非公平的公平设置的 Semaphore。  
  4. Semaphore(int permits, boolean fair)   
  5.           //创建具有给定的许可数和给定的公平设置的 Semaphore。  
//构造方法摘要
Semaphore(int permits) //创建具有给定的许可数和非公平的公平设置的 Semaphore。
Semaphore(int permits, boolean fair) //创建具有给定的许可数和给定的公平设置的 Semaphore。

 

下面的Demo,启动7个线程,每次只让三个线程工作,其它线程阻塞。三个线程的工作时间为一个10000以内的随机数。

 

Java代码   收藏代码
  1. package tags;  
  2.   
  3. import java.util.concurrent.ExecutorService;  
  4.   
  5. import java.util.concurrent.Executors;  
  6.   
  7. import  
  8.   
  9. java.util.concurrent.Semaphore;  
  10.   
  11. public class TestSemaphore {  
  12.   
  13.     public static void  main(String[] args) {  
  14.   
  15.         ExecutorService exec = Executors.newCachedThreadPool();  
  16.   
  17.         // 只能5个线程同时访问  
  18.         final Semaphore sp = new    Semaphore(3);  
  19.   
  20.         // 模拟10个客户端访问  
  21.         for (int index = 0; index < 7; index++) {  
  22.             Runnable rb = new Runnable() {  
  23.                 public void run() {  
  24.                     try {  
  25.                         sp.acquire(); // 获取许可  
  26.                           
  27.                         System.out.println("线程" + Thread.currentThread().getName() +     
  28.                                 "进入,当前已有" + (3-sp.availablePermits()) + "个并发");    
  29.                             //availablePermits()  返回此信号量中当前可用的许可数。  
  30.                           
  31.                         Thread.sleep((long) (Math.random() * 10000));                         
  32.                         System.out.println("线程" + Thread.currentThread().getName() + "即将离开");   
  33.                           
  34.                         sp.release();// 访问完后,释放  
  35.                           
  36.                          System.out.println("线程" + Thread.currentThread().getName() +     
  37.                                  "已离开,当前有" + (3-sp.availablePermits()) + "个并发");    
  38.                     } catch (InterruptedException e) {  
  39.                     }  
  40.                 }  
  41.             };  
  42.             exec.execute(rb);  
  43.         }  
  44.   
  45.         // 退出线程池  
  46.         exec.shutdown();  
  47.     }  
  48. }  
package tags;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;importjava.util.concurrent.Semaphore;public class TestSemaphore {public static void	main(String[] args) {ExecutorService exec = Executors.newCachedThreadPool();// 只能5个线程同时访问final Semaphore sp = new	Semaphore(3);// 模拟10个客户端访问for (int index = 0; index < 7; index++) {Runnable rb = new Runnable() {public void run() {try {sp.acquire(); // 获取许可System.out.println("线程" + Thread.currentThread().getName() +   "进入,当前已有" + (3-sp.availablePermits()) + "个并发");  //availablePermits()  返回此信号量中当前可用的许可数。Thread.sleep((long) (Math.random() * 10000));						System.out.println("线程" + Thread.currentThread().getName() + "即将离开"); sp.release();// 访问完后,释放System.out.println("线程" + Thread.currentThread().getName() +   "已离开,当前有" + (3-sp.availablePermits()) + "个并发");  } catch (InterruptedException e) {}}};exec.execute(rb);}// 退出线程池exec.shutdown();}
}

  结果:

 

线程pool-1-thread-2进入,当前已有2个并发

线程pool-1-thread-3进入,当前已有3个并发

线程pool-1-thread-1进入,当前已有2个并发

线程pool-1-thread-3即将离开

线程pool-1-thread-4进入,当前已有3个并发

线程pool-1-thread-3已离开,当前有3个并发

线程pool-1-thread-2即将离开

线程pool-1-thread-2已离开,当前有2个并发

线程pool-1-thread-7进入,当前已有3个并发

线程pool-1-thread-1即将离开

线程pool-1-thread-5进入,当前已有3个并发

线程pool-1-thread-1已离开,当前有3个并发

线程pool-1-thread-4即将离开

线程pool-1-thread-4已离开,当前有2个并发

线程pool-1-thread-6进入,当前已有3个并发

线程pool-1-thread-7即将离开

线程pool-1-thread-7已离开,当前有2个并发

线程pool-1-thread-6即将离开

线程pool-1-thread-6已离开,当前有1个并发

线程pool-1-thread-5即将离开

线程pool-1-thread-5已离开,当前有0个并发

参考:http://blog.csdn.net/lb85858585/article/details/7273561

JDK:http://www.cjsdn.net/doc/jdk50/java/util/concurrent/Semaphore.html#availablePermits()

 

转载自:http://uule.iteye.com/blog/1539813

 

这篇关于使用Semaphore做并发个数控制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1125489

相关文章

java图像识别工具类(ImageRecognitionUtils)使用实例详解

《java图像识别工具类(ImageRecognitionUtils)使用实例详解》:本文主要介绍如何在Java中使用OpenCV进行图像识别,包括图像加载、预处理、分类、人脸检测和特征提取等步骤... 目录前言1. 图像识别的背景与作用2. 设计目标3. 项目依赖4. 设计与实现 ImageRecogni

python管理工具之conda安装部署及使用详解

《python管理工具之conda安装部署及使用详解》这篇文章详细介绍了如何安装和使用conda来管理Python环境,它涵盖了从安装部署、镜像源配置到具体的conda使用方法,包括创建、激活、安装包... 目录pytpshheraerUhon管理工具:conda部署+使用一、安装部署1、 下载2、 安装3

Mysql虚拟列的使用场景

《Mysql虚拟列的使用场景》MySQL虚拟列是一种在查询时动态生成的特殊列,它不占用存储空间,可以提高查询效率和数据处理便利性,本文给大家介绍Mysql虚拟列的相关知识,感兴趣的朋友一起看看吧... 目录1. 介绍mysql虚拟列1.1 定义和作用1.2 虚拟列与普通列的区别2. MySQL虚拟列的类型2

使用MongoDB进行数据存储的操作流程

《使用MongoDB进行数据存储的操作流程》在现代应用开发中,数据存储是一个至关重要的部分,随着数据量的增大和复杂性的增加,传统的关系型数据库有时难以应对高并发和大数据量的处理需求,MongoDB作为... 目录什么是MongoDB?MongoDB的优势使用MongoDB进行数据存储1. 安装MongoDB

关于@MapperScan和@ComponentScan的使用问题

《关于@MapperScan和@ComponentScan的使用问题》文章介绍了在使用`@MapperScan`和`@ComponentScan`时可能会遇到的包扫描冲突问题,并提供了解决方法,同时,... 目录@MapperScan和@ComponentScan的使用问题报错如下原因解决办法课外拓展总结@

mysql数据库分区的使用

《mysql数据库分区的使用》MySQL分区技术通过将大表分割成多个较小片段,提高查询性能、管理效率和数据存储效率,本文就来介绍一下mysql数据库分区的使用,感兴趣的可以了解一下... 目录【一】分区的基本概念【1】物理存储与逻辑分割【2】查询性能提升【3】数据管理与维护【4】扩展性与并行处理【二】分区的

使用Python实现在Word中添加或删除超链接

《使用Python实现在Word中添加或删除超链接》在Word文档中,超链接是一种将文本或图像连接到其他文档、网页或同一文档中不同部分的功能,本文将为大家介绍一下Python如何实现在Word中添加或... 在Word文档中,超链接是一种将文本或图像连接到其他文档、网页或同一文档中不同部分的功能。通过添加超

Linux使用fdisk进行磁盘的相关操作

《Linux使用fdisk进行磁盘的相关操作》fdisk命令是Linux中用于管理磁盘分区的强大文本实用程序,这篇文章主要为大家详细介绍了如何使用fdisk进行磁盘的相关操作,需要的可以了解下... 目录简介基本语法示例用法列出所有分区查看指定磁盘的区分管理指定的磁盘进入交互式模式创建一个新的分区删除一个存

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学