1.Semaphore 是什么


Semaphore 通常我们叫它信号量, 可以用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理的使用资源。

可以把它简单的理解成我们停车场入口立着的那个显示屏,每有一辆车进入停车场显示屏就会显示剩余车位减1,每有一辆车从停车场出去,显示屏上显示的剩余车辆就会加1,当显示屏上的剩余车位为0时,停车场入口的栏杆就不会再打开,车辆就无法进入停车场了,直到有一辆车从停车场出去为止。


2.Semaphore常用方法


Semaphore 最中要的两个方法是Semaphore#acquire 和Semaphore#release方法

  • acquire:当前线程会尝试去同步队列获取一个令牌,当获取成功时得到令牌,获取失败的时候就挂起等待
  • release:当前线程尝试释放一个令牌,释放令牌成功之后,同时会唤醒同步队列中的另一个线程,让其尝试获取令牌,如果它获取令牌成功则使其继续运行
//参考JDK 11
public class Semaphore implements java.io.Serializable {private final Sync sync;//获取一个许可证令牌//在获取到许可证令牌、或者被其他线程调用中断之前线程一直处于阻塞状态public void acquire() throws InterruptedException {sync.acquireSharedInterruptibly(1);}//获取指定数量许可证令牌//在获取到许可证令牌、或者被其他线程调用中断、或超时之前线程一直处于阻塞状态public void acquire(int permits) throws InterruptedException {if (permits < 0) throw new IllegalArgumentException();sync.acquireSharedInterruptibly(permits);}//获取一个许可证令牌,在获取到令牌之前线程一直处于阻塞状态public void acquireUninterruptibly() {sync.acquireShared(1);}//获取指定数量令牌,在获取到令牌之前线程一直处于阻塞状态public void acquireUninterruptibly(int permits) {if (permits < 0) throw new IllegalArgumentException();sync.acquireShared(permits);}//尝试获得令牌,返回获取令牌成功或失败,不阻塞线程public boolean tryAcquire() {return sync.nonfairTryAcquireShared(1) >= 0;}//获取给定数量的许可证(如果可用),//如果可用的许可证令牌足够, 立即返回值true,将可用许可证数量减少给定数量。//如果可用的许可证令牌不足,则此方法将立即返回值false,并且可用许可证的数量不变。public boolean tryAcquire(int permits) {if (permits < 0) throw new IllegalArgumentException();return sync.nonfairTryAcquireShared(permits) >= 0;}//尝试获得许可证令牌,在超时时间内循环尝试获取,直到尝试获取成功或超时返回,不阻塞线程public boolean tryAcquire(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireSharedNanos(1, 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();}//清空令牌把可用许可证令牌数置为0,返回清空令牌的数量public int drainPermits() {return sync.drainPermits();}//查询信号量公平设置true 公平 false非公平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();}}

3.Semaphore 使用场景


通常用于那些资源有明确访问数量限制的场景,常用于限流 。比如:数据库连接池,同时进行连接的线程有数量限制,连接不能超过一定的数量,当连接达到了限制数量后,后面的线程只能排队等前面的线程释放了数据库连接才能获得数据库连接。

举个例子, 停车场场景,车位数量有限,同时只能容纳多少台车,车位满了之后只有等里面的车离开停车场外面的车才可以进入。例如下面的测试代码

  • 创建令牌数为2的信号量,表示车库只有2个车位
  • 循环创建10个线程尝试获取信号量的令牌,模拟表示车获取空闲车位
  • 线程获取信号量后5秒释放,表示每辆车最多停5秒
import java.util.concurrent.Semaphore;public class SemaphoreTest {public static void main(String[] args) throws InterruptedException {//测试信号量为2Semaphore semaphore=new Semaphore(2);for (int i = 0; i < 10; i++) {Thread thread=new Thread(new Runnable() {@Overridepublic void run() {try {semaphore.acquire();System.out.println(Thread.currentThread().getName()+" in");int time=5000;Thread.sleep(time);System.out.println(Thread.currentThread().getName()+":semaphore#release ,after "+time/1000+"s");semaphore.release();;} catch (InterruptedException e) {e.printStackTrace();}}},"Thread No."+i);thread.start();}}
}

测试结果:因为信号量令牌数量为2,所以开始时只有2个线程acquire获取到令牌,打印 in ,当两个线程release 释放令牌后,其他线程中的两个线程才能获取到令牌,再次in进入

Thread No.0 in
Thread No.3 in
Thread No.0:semaphore#release ,after 5s
Thread No.3:semaphore#release ,after 5s
Thread No.7 in
Thread No.5 in
Thread No.7:semaphore#release ,after 5s
Thread No.5:semaphore#release ,after 5s
Thread No.4 in
Thread No.1 in
Thread No.1:semaphore#release ,after 5s
Thread No.4:semaphore#release ,after 5s
Thread No.6 in
Thread No.8 in
Thread No.6:semaphore#release ,after 5s
Thread No.8:semaphore#release ,after 5s
Thread No.2 in
Thread No.9 in
Thread No.2:semaphore#release ,after 5s
Thread No.9:semaphore#release ,after 5s

上一篇:JAVA多线程同步计数器CountDownLatch作用

JAVA多线程信号量Semaphore相关推荐

  1. java 多线程 信号量_Java核心-多线程(7)-并发控制器-Semaphore信号量

    Semaphore是非常有用的一个多线程并发控制组件(Java还有CountDownLatch.CyclicBarrier.Exchanger多线程组件),它相当于是一个并发控制器,是用于管理信号量的 ...

  2. Java多线程 信号量和屏障实现控制并发线程数量,主线程等待所有线程执行完毕2

    项目需求需要多线程执行计算任务,主线程要等所有线程执行完毕,记录执行结果.另外要控制并行线程数量,防止用光内存.实现测试代码如下. 测试代码如下: public class ThreadsTest { ...

  3. Java多线程 信号量和屏障实现控制并发线程数量,主线程等待所有线程执行完毕1

    测试代码如下: public class ThreadsTest implements Runnable{private ExecutorService threadPool=Executors.ne ...

  4. Java多线程-通讯方式

    Java多线程-通讯方式 线程之间为什么要通信? 通信的目的是为了更好的协作,线程无论是交替式执行,还是接力式执行,都需要进行通信告知.那么java线程是如何通信的呢,大致有以下六种方式. Java线 ...

  5. java多线程的同步控制_Java多线程并发控制工具信号量Semaphore,实现原理及案例...

    信号量(Semaphore)是Java多线程兵法中的一种JDK内置同步器,通过它可以实现多线程对公共资源的并发访问控制.一个线程在进入公共资源时需要先获取一个许可,如果获取不到许可则要等待其它线程释放 ...

  6. Android 价值千万java多线程同步 lt;五CountDownLatch(计数器)和Semaphore(信号量)

    1).Android 价值千万   java线程专题:Wait&notify&join&Yield http://blog.csdn.net/whb20081815/artic ...

  7. Java多线程:Semaphore

    自从5.0开始,jdk在java.util.concurrent包里提供了Semaphore 的官方实现. Java 5.0里新加了4个协调线程间进程的同步装置,它们分别是: Semaphore, C ...

  8. Java多线程(八)之Semaphore、CountDownLatch、CyclicBarrier、Exchanger

    一.引言 Semaphore               :一个计数信号量 CountDownLatch          :一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线 ...

  9. java线程——信号量(Semaphore)+障栅(CyclicBarrier)

    [0]README 0.1)以下内容转自网络,旨在理清 "java线程--信号量(Semaphore)+障栅(CyclicBarrier)"的相关知识 [1]信号量 1.1)信号量 ...

最新文章

  1. MPB:亚热带生态所葛体达组-原位酶谱法高分辨率实时检测土壤微界面酶活分布...
  2. Linux 引导过程内幕
  3. C++ 判断点是否在圆的内部
  4. 物理光学4 反射与折射中的一些特殊现象
  5. [BZOJ 2957]楼房重建(线段树)
  6. 反射,System.Type类
  7. android 复制u盘文件到手机本地_如何导出Android中的文件(把Android当做U盘)
  8. 负数如何归一化处理_机器学习之数据预处理
  9. 【函数的定义、调用(嵌套调用、递归调用)、声明、函数的分类(有无返回值、有无参数)、变量(自动变量与静态变量、局部变量与全局变量、只读变量)】(学习笔记7--函数)
  10. 1.8_heapq模块_优先队列
  11. bootbox.confirm 官方例子 网址
  12. 图层蒙版和图层剪贴路径_PS蒙版解读:快速蒙版、图层蒙版、剪贴蒙版、矢量蒙版(二)...
  13. Linux清空回收站
  14. 【MATLAB】rem和mod函数的区别
  15. 12面魔方公式图解法_高手指教一下十二面魔方怎么拼?
  16. 疫情地图 | EXCEL制作疫情风险地地图
  17. /usr/bin/ld cannot find -lGL
  18. vue+iview 兼容IE11浏览器
  19. python 实践--新闻聚合
  20. 360网站卫士的IP段添加进服务器的白名单中

热门文章

  1. 【计算机专业毕设之基于机器学习的大葱价格预测可视化分析-哔哩哔哩】 https://b23.tv/GLkWcjb
  2. JAVA程序员工作常用英语(细心整理)计算机常用英语汇总
  3. 为老化的Windows Mobile 6.x设备呼吸新生命
  4. Spring AMQP参考手册
  5. 上周听SMARTCLIENT讲座感受
  6. 微信小程序云开发Collection.watch如何关闭
  7. Python学习笔记Day03
  8. linux配置yum镜像源
  9. attempt to configure ONS in FanManager failed with oracle.ons.NoServersAvailable: Subscription time
  10. Communication-Efficient Learning of Deep Networks from Decentralized Data