在java中,提供了信号量Semaphore的支持。Semaphore是一个计数信号量,它的本质是一个"共享锁",或者说是一个功能完毕的计数器。它对控制一定资源的消费与回收有着很重要的意义,信号量常常用于多线程的代码中,并能监控有多少数目的线程等待获取资源,并且通过信号量可以得知可用资源的数目等等,这里总是在强调“数目”二字,但不能指出来有哪些在等待,哪些资源可用。

信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。

1. 相关方法

1.1 Semaphore对象的创建

// 创建具有给定的许可数和非公平的公平设置的 Semaphore。
Semaphore(int permits)
// 创建具有给定的许可数和给定的公平设置的 Semaphore。
Semaphore(int permits, boolean fair)

其中,permits:初始化可用的许可数目,fair: 若该信号量保证在征用时按FIFO的顺序授予许可,则为true,否则为false。

注意,当设置permits为0时,可以实现wait和notify类似的操作。

1.2 从信号量中获得许可

// 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。
void acquire()
// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断。
void acquire(int permits)
// 从此信号量中获取许可,在有可用的许可前将其阻塞。
void acquireUninterruptibly()
// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。
void acquireUninterruptibly(int permits)

1.3  释放一个许可,并返回信号量

// 释放一个许可,将其返回给信号量。
void release()
// 释放给定数目的许可,将其返回到信号量。
void release(int permits)

1.4 其他

// 返回此信号量中当前可用的许可数。
int availablePermits()
// 获取并返回立即可用的所有许可。
int drainPermits()
// 返回一个 collection,包含可能等待获取的线程。
protected Collection<Thread> getQueuedThreads()
// 返回正在等待获取的线程的估计数目。
int getQueueLength()
// 查询是否有线程正在等待获取。
boolean hasQueuedThreads()
// 如果此信号量的公平设置为 true,则返回 true。
boolean isFair()
// 根据指定的缩减量减小可用许可的数目。
protected void reducePermits(int reduction)// 返回标识此信号量的字符串,以及信号量的状态。
String toString()
// 仅在调用时此信号量存在一个可用许可,才从信号量获取许可。
boolean tryAcquire()
// 仅在调用时此信号量中有给定数目的许可时,才从此信号量中获取这些许可。
boolean tryAcquire(int permits)
// 如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被中断,则从此信号量获取给定数目的许可。
boolean tryAcquire(int permits, long timeout, TimeUnit unit)
// 如果在给定的等待时间内,此信号量有可用的许可并且当前线程未被中断,则从此信号量获取一个许可。
boolean tryAcquire(long timeout, TimeUnit unit)

2. 代码实例: 

20个人去银行存款,但是该银行只有两个办公柜台,有空位则上去存钱,没有空位则只能去排队等待。

package com.xhj.thread;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;/*** 线程信号量Semaphore的运用* * @author XIEHEJUN* */
public class SemaphoreThread {private int a = 0;/*** 银行存钱类*/class Bank {private int account = 100;public int getAccount() {return account;}public void save(int money) {account += money;}}/*** 线程执行类,每次存10块钱*/class NewThread implements Runnable {private Bank bank;private Semaphore semaphore;public NewThread(Bank bank, Semaphore semaphore) {this.bank = bank;this.semaphore = semaphore;}@Overridepublic void run() {int b = a++;if (semaphore.availablePermits() > 0) {System.out.println("线程" + b + "启动,进入银行,有位置立即去存钱");} else {System.out.println("线程" + b + "启动,进入银行,无位置,去排队等待等待");}try {semaphore.acquire();bank.save(10);System.out.println(b + "账户余额为:" + bank.getAccount());Thread.sleep(1000);System.out.println("线程" + b + "存钱完毕,离开银行");semaphore.release();} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {SemaphoreThread test = new SemaphoreThread();test.useThread();}/*** 建立线程,调用内部类,开始存钱*/public void useThread() {Bank bank = new Bank();// 定义2个信号量Semaphore semaphore = new Semaphore(2);// 建立一个缓存线程池ExecutorService es = Executors.newCachedThreadPool();// 建立20个线程for (int i = 0; i < 20; i++) {// 执行一个线程es.submit(new Thread(new NewThread(bank, semaphore)));}// 关闭线程池es.shutdown();// 从信号量中获取两个许可,并且在获得许可之前,一直将线程阻塞semaphore.acquireUninterruptibly(2);System.out.println("到点了,工作人员要吃饭了");// 释放两个许可,并将其返回给信号量semaphore.release(2);}
}

本文参考自:java笔记--对信号量Semaphore的理解与运用和Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例

【java】信号量机制相关推荐

  1. Java中的信号量机制

    前言   在多线程并发编程中,经常需要进行线程同步和互斥,以确保共享资源的正确访问和操作.Java中提供了信号量机制,通过计数器来控制线程的并发访问,保证对共享资源的访问是同步的.本文将介绍信号量机制 ...

  2. 卡住无法查看到所有进程_进程同步 进程互斥 软件和硬件实现方式 信号量机制 信号量机制实现进程同步,进程互斥,前驱关系...

    参考:https://www.bilibili.com/video/av31584226/?p=9 进程具有异步性的特征,异步性是指,各并发执行的进程以各自独立的,不可预知的速度向前推进. 回忆我们之 ...

  3. 面试必会系列 - 1.5 Java 锁机制

    本文已收录至 github,完整图文:https://github.com/HanquanHq/MD-Notes 面试必会系列专栏:https://blog.csdn.net/sinat_424833 ...

  4. 【操作系统】进程管理(五)—— 信号量机制

    [操作系统]进程管理(五)-- 信号量机制 前言 一.信号量机制 信号量机制--整型信号量 信号量机制--记录型信号量 二.用信号量机制实现进程互斥.同步.前驱关系 信号量机制实现进程互斥 信号量机制 ...

  5. 五、深入了解信号量机制(大彻大悟篇)内附经典生产者消费者等线程同步问题

    一.信号量机制 复习回顾+思考:之前学习的这些进程互斥的解决方案分别存在哪些问题? 进程互斥的四种软件实现方式(单标志法.双标志先检查.双标志后检查.Peterson算法 ) 进程互斥的三种硬件实现方 ...

  6. 进程同步之信号量机制(pv操作)

    1.信号量机制 信号量机制即利用pv操作来对信号量进行处理. 什么是信号量?信号量(semaphore)的数据结构为一个值和一个指针,指针指向等待该信号量的下一个进程.信号量的值与相应资源的使用情况有 ...

  7. java事件处理模型_从零开始理解JAVA事件处理机制(3)

    我们连续写了两小节的教师-学生的例子,必然觉得无聊死了,这样的例子我们就是玩上100遍,还是不知道该怎么写真实的代码.那从本节开始,我们开始往真实代码上面去靠拢. 事件最容易理解的例子是鼠标事件:我们 ...

  8. GCD之信号量机制二

    在前面GCD之信号量机制一中介绍了通过信号量设置并行最大线程数,依此信号量还可以防止多线程访问公有变量时数据有误,下面的代码能说明. 1.下面是不采用信号量修改公有变量的值 dispatch_grou ...

  9. 两道面试题,带你解析Java类加载机制

    2019独角兽企业重金招聘Python工程师标准>>> 在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题: class Grandpa {static ...

  10. Java类加载机制详解【java面试题】

    Java类加载机制详解[java面试题] (1)问题分析: Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数 ...

最新文章

  1. 一个球从100米高度自由落下,每次落地后反弹回原高度的一半; * 再落下,求在第几次之后反弹高度小于0.1米, * 并计算在这一次落地时共经过多少米?...
  2. Linux文件夹的打开方式
  3. 高等数学下-赵立军-北京大学出版社-题解-练习12.2
  4. python manager与basemanager_使用Python多处理管理器(BaseManager/SyncManager)与远程计算机共享队列时出现管道中断...
  5. php微信拍照图库js接口,ThinkPHP微信实例——JSSDK图像接口多张图片上传下载并将图片流写入本地...
  6. apache的es的原理_Elasticsearch Lucene 数据写入原理 | ES 核心篇
  7. 28.4 kvm介绍 28.5 Centos7上安装KVM 28.6 配置网卡 28.7 创建虚拟机安装CentOS7
  8. PCL八叉树的包围盒研究
  9. 国外浏览器哪个好用?国外浏览器排名
  10. 8086汇编基础 8080,8088,8086,80286,80386的地址线,数据线宽度
  11. 关于顶级域名、二级域名、子域名的问题
  12. EM(expection maxium)算法
  13. Just Cause系列游戏品鉴
  14. html钢琴块游戏源码,好玩的钢琴块游戏
  15. sap客户信贷_通过SAP ABAP接口修改客户信贷主数据
  16. linux下的go富集分析,GO富集分析
  17. 纯真数据库理解及根据IP定位地区
  18. 可用的rtmp,rtsp,http网络流地址(2020-08-27更新)
  19. 【小程序】提交成功和失败界面示例(图文+代码)
  20. 莫名其妙的“配置系统未能初始化”异常

热门文章

  1. java ee 结构图,javaee体系结构图
  2. 最新版校园招聘进大厂系列----------(5)百度篇 -----未完待续
  3. Visual Attention Network
  4. java使用xmlWorkerHelper将html转pdf
  5. 手把手教你如何生成自己的二维码
  6. 微信分组可见怎么实现android,android如何管理微信分组
  7. 解决eclipse安装Darkest Dark Theme报错
  8. 非线性最小二乘法曲线拟合
  9. TimePicker使用全解
  10. Detours注入DLL钩子入门教程