当前位置: 首页 > news >正文

JUC之限流利器 Semaphore

如果大家对java架构相关感兴趣,可以关注下面公众号,会持续更新java基础面试题, netty, spring boot,spring cloud等系列文章,一系列干货随时送达, 超神之路从此展开, BTAJ不再是梦想!

架构殿堂

概念

Semaphore 是一个计数信号量,必须由获取它的线程释放。

常用于限制可以访问某些资源的线程数量,例如通过 Semaphore 限流。

主要方法摘要

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

// 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。
void acquire()
// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断。
void acquire(int permits)
// 从此信号量中获取许可,在有可用的许可前将其阻塞。
void acquireUninterruptibly()
// 从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。
void acquireUninterruptibly(int permits)
// 返回此信号量中当前可用的许可数。
int availablePermits()
// 获取并返回立即可用的所有许可。
int drainPermits()
// 返回一个 collection,包含可能等待获取的线程。
protected Collection<Thread> getQueuedThreads()
// 返回正在等待获取的线程的估计数目。
int getQueueLength()
// 查询是否有线程正在等待获取。
boolean hasQueuedThreads()
// 如果此信号量的公平设置为 true,则返回 true。
boolean isFair()
// 根据指定的缩减量减小可用许可的数目。
protected void reducePermits(int reduction)
// 释放一个许可,将其返回给信号量。在释放许可之前,必须先获获得许可
void release()
// 释放给定数目的许可,将其返回到信号量。
void release(int permits)
// 返回标识此信号量的字符串,以及信号量的状态。
String toString()
// 尝试获取一个许可,若获取成功返回true,若获取失败返回false, 仅在调用时此信号量存在一个可用许可,才从信号量获取许可。
boolean tryAcquire()
// 仅在调用时此信号量中有给定数目的许可时,才从此信号量中获取这些许可。
boolean tryAcquire(int permits)
// 如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被中断,则从此信号量获取给定数目的许可。
boolean tryAcquire(int permits, long timeout, TimeUnit unit)
// 如果在给定的等待时间内,此信号量有可用的许可并且当前线程未被中断,则从此信号量获取一个许可。
boolean tryAcquire(long timeout, TimeUnit unit)

上面是基本常见的方法,Semaphore底层是由AQS和Uasafe完成的,调用的是

protected final boolean compareAndSetState(int expect, int update) {
    // See below for intrinsics setup to support this
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

步骤

  1. 初始化
  2. 增加
  3. 减少

示例

public class SemaphoreDemo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();

        //信号量,只允许 3个线程同时访问
        final Semaphore semaphore = new Semaphore(3);

        for (int i=0;i<10;i++){
            final long num = i;
            executorService.submit(new Runnable() {
                public void run() {
                    try {
                        //获取许可
                        semaphore.acquire();
                        //执行
                        System.out.println("执行: " + num);
                        Thread.sleep(new Random().nextInt(5000)); // 模拟随机执行时长
                        //释放
                        semaphore.release();
                        System.out.println("释放..." + num);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        executorService.shutdown();
    }
}

总结

​ Semaphore主要用于控制当前活动线程数目,就如同停车场系统一般,而Semaphore则相当于看守的人,用于控制总共允许停车的停车位的个数,而对于每辆车来说就如同一个线程,线程需要通过acquire()方法获取许可,而release()释放许可。如果许可数达到最大活动数,那么调用acquire()之后,便进入等待队列,等待已获得许可的线程释放许可,从而使得多线程能够合理的运行。

如果大家对java架构相关感兴趣,可以关注下面公众号,会持续更新java基础面试题, netty, spring boot,spring cloud等系列文章,一系列干货随时送达, 超神之路从此展开, BTAJ不再是梦想!

架构殿堂

相关文章:

  • 日程管理APP测试用例
  • volatile 底层原理以及特性详解
  • js---05 自定义属性
  • 深入解析JMM原理
  • 为Redmine的项目加上起止时间
  • 详尽Netty(一):初探netty
  • Php基础知识测试题
  • 设计模式(四):建造者模式的详细解析
  • [swust1745] 餐巾计划问题(费用流)
  • 详尽Netty(二):源码环境搭建
  • AssetBundle管理机制(上)
  • 详尽Netty(三):Channel
  • 循序渐进之Spring AOP(5) - 创建切面
  • 牛逼!阿里推出国产开源的jdk! 快来试试吧!
  • ES6 中的let 声明变量
  • 《深入 React 技术栈》
  • 30天自制操作系统-2
  • Android单元测试 - 几个重要问题
  • ECMAScript入门(七)--Module语法
  • js操作时间(持续更新)
  • MYSQL 的 IF 函数
  • TypeScript迭代器
  • ⭐ Unity 开发bug —— 打包后shader失效或者bug (我这里用Shader做两张图片的合并发现了问题)
  • 阿里云购买磁盘后挂载
  • 每天10道Java面试题,跟我走,offer有!
  • 如何在GitHub上创建个人博客
  • 深度解析利用ES6进行Promise封装总结
  • 深度学习中的信息论知识详解
  • 算法-图和图算法
  • 线性表及其算法(java实现)
  • 项目实战-Api的解决方案
  • RDS-Mysql 物理备份恢复到本地数据库上
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 我们雇佣了一只大猴子...
  • # Apache SeaTunnel 究竟是什么?
  • #QT(串口助手-界面)
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (力扣题库)跳跃游戏II(c++)
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用
  • (实战篇)如何缓存数据
  • (一)基于IDEA的JAVA基础12
  • (转)ABI是什么
  • (转)负载均衡,回话保持,cookie
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • *2 echo、printf、mkdir命令的应用
  • . Flume面试题
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .NET Core 2.1路线图
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .net core 控制台应用程序读取配置文件app.config
  • .NET 中的轻量级线程安全
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)