Semaphore的作用是,限制线程通行的数量,如果线程进入时达到通行数量,便等待其它正在通行的线程释放。

  • acquire()
    获取通行
  • release()
    释放通行
  • availablePermits()
    查看通行剩余次数
  • int drainPermits()
    缩减剩余通行次数为0,并返回缩减量
  • reducePermits(int)
    缩减通行次数为指定次数
  • boolean isFair()
    查看是否公平分配通行
  • boolean hasQueuedThreads()
    查看是否有线程在排队
  • int getQueueLength()
    查看排队的长度
  • Collection<Thread> getQueuedThreads()
    查看排队中的所有线程

源码:

/*** @since 1.5* @author Doug Lea*/
public class Semaphore implements java.io.Serializable {private static final long serialVersionUID = -3222578661600680210L;private final Sync sync;public Semaphore(int permits) {// 默认使用非公平锁,设置初始的剩余通行量sync = new NonfairSync(permits);}public Semaphore(int permits, boolean fair) {// 参数决定使用公平还是非公平锁,设置初始的剩余通行量sync = fair ? new FairSync(permits) : new NonfairSync(permits);}abstract static class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID = 1192457210091910933L;Sync(int permits) {// 设置初始的剩余通行量
            setState(permits);}final int getPermits() {// 获取剩余通行量return getState();}final int nonfairTryAcquireShared(int acquires) {for (;;) {int available = getState();int remaining = available - acquires;// 设置获取后的剩余通行量// 当剩余量小于0时,则阻塞,否则通行if (remaining < 0 || compareAndSetState(available, remaining))return remaining;}}protected final boolean tryReleaseShared(int releases) {for (;;) {int current = getState();int next = current + releases;// 不允许释放量是负数if (next < current) // overflowthrow new Error("Maximum permit count exceeded");// 设置释放后的剩余通行量,返回释放成功,表示需要通知下一个线程通行if (compareAndSetState(current, next))return true;}}final void reducePermits(int reductions) {for (;;) {int current = getState();int next = current - reductions;// 不允许缩减值是负数if (next > current) // underflowthrow new Error("Permit count underflow");// 设置缩减后的剩余通行量if (compareAndSetState(current, next))return;}}final int drainPermits() {for (;;) {int current = getState();// 直接把剩余通行量设置为0if (current == 0 || compareAndSetState(current, 0))return current;}}}static final class NonfairSync extends Sync {private static final long serialVersionUID = -2694183684443567898L;NonfairSync(int permits) {super(permits);}protected int tryAcquireShared(int acquires) {return nonfairTryAcquireShared(acquires);}}static final class FairSync extends Sync {private static final long serialVersionUID = 2014338818796000944L;FairSync(int permits) {super(permits);}protected int tryAcquireShared(int acquires) {for (;;) {// 如果当前线程不位于队头,则阻塞if (hasQueuedPredecessors())return -1;int available = getState();int remaining = available - acquires;// 设置获取后的剩余通行量// 当剩余量小0时,则阻塞,否则通行if (remaining < 0 || compareAndSetState(available, remaining))return remaining;}}}public void acquire() throws InterruptedException {// 获取一次通行,可中断sync.acquireSharedInterruptibly(1);}public void acquireUninterruptibly() {// 获取一次通行sync.acquireShared(1);}public boolean tryAcquire() {// 尝试获取一次通行return sync.nonfairTryAcquireShared(1) >= 0;}public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException {// 尝试在指定时间内获取一次通行return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));}public void acquire(int permits) throws InterruptedException {if (permits < 0)throw new IllegalArgumentException();// 获取指定通行次数,可中断
        sync.acquireSharedInterruptibly(permits);}public void acquireUninterruptibly(int permits) {if (permits < 0)throw new IllegalArgumentException();// 获取指定通行次数
        sync.acquireShared(permits);}public boolean tryAcquire(int permits) {if (permits < 0)throw new IllegalArgumentException();// 尝试获取指定通行次数return sync.nonfairTryAcquireShared(permits) >= 0;}public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException {if (permits < 0)throw new IllegalArgumentException();// 尝试在指定时间内获取通行return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));}public void release() {// 释放一次通行sync.releaseShared(1);}public void release(int permits) {if (permits < 0)throw new IllegalArgumentException();// 释放指定的通行次数
        sync.releaseShared(permits);}public int availablePermits() {// 返回剩余的通行量return sync.getPermits();}public int drainPermits() {// 直接把通行量设置为0return sync.drainPermits();}protected void reducePermits(int reduction) {if (reduction < 0)throw new IllegalArgumentException();// 缩减通行量
        sync.reducePermits(reduction);}public boolean isFair() {// 返回是否公平锁(即是否公平分配通行)return sync instanceof FairSync;}public final boolean hasQueuedThreads() {// 返回队列中是否有线程return sync.hasQueuedThreads();}public final int getQueueLength() {// 返回队列的长度return sync.getQueueLength();}protected Collection<Thread> getQueuedThreads() {// 返回队列中的所有线程return sync.getQueuedThreads();}public String toString() {return super.toString() + "[Permits = " + sync.getPermits() + "]";}
}

转载于:https://www.cnblogs.com/hvicen/p/6242142.html

多线程条件通行工具——Semaphore相关推荐

  1. 5.3多线程条件变量

    多线程条件变量应用例子 Input_manager.h InputOpr 结构体添加 进程 ID :pthread_t t_TreadID; int AllInputDevicesInit(void) ...

  2. CSerialPort多线程串口编程工具详解

    1.前言 既然有了MSComm这种简单粗暴的控件,为什么还需要CSerialPort类?这是因为与前者相比,这个类在程序的发布上不需要加入其他的文件,而且CSerialPort提供给我们的函数都是开放 ...

  3. 无锁编程[0]__多线程条件下的计数器__原子的加/减/与/或/异或操作__sync_fetch_and_add,__sync_add_and_fetch等

    多线程条件下的计数器是服务器开发的常用操作,比如异步请求sessionid的活动,通常我们会用: 1.加锁取sessionid 2.分段取sessionid (在初始化阶段完成多线程分段取sessio ...

  4. mysql多线程导出_MySQL多线程导入导出工具Mydumper

    MySQL多线程导入导出工具Mydumper 今天从线上使用mysqldump将数据表从一个库导入到另外一个库,结果导出速度超级慢.于是网上搜了搜发现这个东东.测试之后发现还不错.分享给大家. 简单介 ...

  5. 转Linux多线程条件下的计数器 2011-11-15 00:00中国IT实验室佚名

    Linux多线程条件下的计数器 2011-11-15 00:00中国IT实验室佚名 字号:A+|A- 最近编码需要实现多线程环境下的计数器操作,统计相关事件的次数.下面是一些学习心得和体会.不敢妄称原 ...

  6. linux 多线程 semaphore ,Linux下多线程编程-Pthread和Semaphore使用.doc

    比锄戴垒丛共麦溺庄哆氏葫季袒飞闲棉铆稼椰悲倘寓矩案铺汞嫡懂伸腑箩五穗颗撩护尚巷苯宅瑚铱焕涅职枝怎摔什街杠写冻泡峡蠢舀以咽铝皇篮糠村墟凤帜攒摧定畜遁陛葛杯复妄婚赣续踌肖祷就抖帘荒徘魂圭焙酸劈待钞林讯啊铂 ...

  7. gFTP - 多线程 FTP 客户端工具

    gFTP - 多线程 FTP 客户端工具 https://www.gftp.org/ gFTP is a free multithreaded file transfer client for *NI ...

  8. JAVA多线程-常用JUC工具类及阻塞队列

    工具类 CountDownLactch 简述 允许一个或多个线程等待,直到在其他线程中执行的一组操作完成,同步辅助. CountDownLatch 类用给定的计数初始化. await 方法阻塞,直到由 ...

  9. 219-C++多线程(条件变量)

    操作1(不加线程) 操作2(引入多线程) 打印的结果不是我们想要的! 这里造成结果混乱的原因是什么? 原因是: 并发执行,多线程抢占资源. 这是一种异步执行方案.当我们程序链接编译通过之后,我们从主函 ...

最新文章

  1. JAVA事物API JTA
  2. salt return mysql_mysql中储存salt返回结果
  3. 【Java报错】Greenplum数据库报错 could not determine data type of parameter $2. 问题解决(踩坑分享)
  4. 随想录(设计软件模块的接口)
  5. aws rds监控慢sql_使用AWS Database迁移服务进行AWS RDS SQL Server迁移
  6. - 贪心基础入门讲解二——活动安排问题
  7. 《疯狂的站长》读后感2
  8. sql查询将字段值转换成汉字
  9. 2022-2027年中国智能硬件行业市场深度分析及发展战略规划报告
  10. 遥感中为什么要使用微波
  11. O2O模式的赢利点有哪些?
  12. 反斜杠“\”与斜杠“/” 的区别
  13. win+ubuntu安装Nvidia显卡驱动
  14. Nimbus线上AMA内容记录-第四期
  15. mysql中flush tables和flush tables with read lock详解
  16. 人工智能前沿——无人自动驾驶技术
  17. 【python爬虫实战】批量下载网站视频
  18. int数据类型matlab,MATLAB学习笔记—数据类型
  19. ADS能量之锥是什么项目?为什么这么多人玩?
  20. Java+JSP基于ssm广州市家教中介服务网站

热门文章

  1. [詹兴致矩阵论习题参考解答]习题1.13
  2. [转载] 华中科技大学期刊分类办法
  3. iOS - 集成SDK问题
  4. [fzu 2273]判断两个三角形的位置关系
  5. initrd的启动过程
  6. 当你遇到modifying layer that is being finalized的时候怎么办?
  7. 十大非著名之父:手机,黑莓,iPod,FORTRAN,远程办公,鼠标,垃圾邮件,DSL,Java,WIFI说,我爸是...-asp.net关注...
  8. JNI系列(1):基础篇
  9. [Ajax] jQuery中的Ajax -- 02-jQuery中的三级联动
  10. [jQuery原理] jQuery基本结构