使用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

相关文章

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

springboot中使用okhttp3的小结

《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

Java中的抽象类与abstract 关键字使用详解

《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

MyBatis ParameterHandler的具体使用

《MyBatisParameterHandler的具体使用》本文主要介绍了MyBatisParameterHandler的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录一、概述二、源码1 关键属性2.setParameters3.TypeHandler1.TypeHa