Java 信号量机制的实践用途之——流量控制

信号量机制

使用java.util.concurrent下的semaphore类作为信号量

用途

设置一个信号量Map,需要时从此Map中get(特定ID)信号量来控制访问请求数量,以实现对单个请求的流量控制,增加系统稳定性。

用法

  1. 编写SemaphoreManager实现对信号量统一管理
    1. 声明信号量Map Map<Long, Semaphore> semaphoreMap
    2. 编写初始化信号量的方法init(args...),设置初始大小的信号量Map
    3. 编写获取信号量的方法(getSemaphore(args...))、创建信号量方法(createSemaphore(size)),创建信号量时,直接new Semaphore(size)对象即可。

使用时可以在项目初始化方法中、aop中、或相应业务代码中引入使用。

以下是代码部分

SemaphoreManager

java 复制代码
@Component
public class SemaphoreManager {

    @Resource
    private DisConfig disConfig;

    private Map<Long, Semaphore> semaphoreMap = new HashMap<>();

    /**
     * 初始化信号量对象
     *
     * @param list 对象信息列表
     */
    public void init(Collection<ObjectDO> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        // 为每个第三方系统生成一个信号量对象
        for (ObjectDO objectDO: list) {
            // 创建信号量对象
            semaphoreMap.put(objectDO.getId(), createSemaphore(objectDO.getMaxConcurrentNum()));
        }
    }

    /**
     * 获取信号量对象
     *
     * @return 信号量对象
     */
    public Semaphore getSemaphore() {
        ObjectContext context = ContextManager.getContext();
        if (context == null) {
            return null;
        }
        return getSemaphore(context.getObjectId(), context.getMaxConcurrentNum());
    }

    /**
     * 获取信号量对象
     *
     * @param objectId 对象ID
     * @param maxConcurrentNum 最大并发数
     * @return 信号量对象
     */
    private Semaphore getSemaphore(Long objectId, Integer maxConcurrentNum) {

        if (semaphoreMap == null) {
            return null;
        }

        // 获取当前对接通道的信号量对象
        Semaphore semaphore = semaphoreMap.get(objectId);
        if (semaphore != null) {
            return semaphore;
        }

        synchronized (objectId.toString().intern()) {
            semaphore = createSemaphore(maxConcurrentNum);
            semaphoreMap.put(objectId, semaphore);
        }

        return semaphore;
    }

    /**
     * 创建信号量对象
     *
     * @param maxConcurrentNum 最大并发数
     * @return 信号量对象
     */
    private Semaphore createSemaphore(Integer maxConcurrentNum) {

        // 如果DB中没有设置则使用disconf中设置的默认值
        if (maxConcurrentNum == null || maxConcurrentNum == 0) {
            maxConcurrentNum = disConfig.getMaxSemp();
        }

        if (maxConcurrentNum == 0) {
            maxConcurrentNum = 100;
        }

        return new Semaphore(maxConcurrentNum);
    }

}

代码使用实践

java 复制代码
                Boolean isAcq = false;
                // 获取信号量对象
                semaphore = semaphoreManager.getSemaphore();

                if (semaphore != null) {
                    // 获取信号量
                    isAcq = semaphore.tryAcquire();
                    // 获取失败时说明请求量过大, 直接返回异常信息
                    AssertUtil.isTrue(isAcq, EnumResultCode.THIRD_SLOWLY);
                }
相关推荐
caoerzhong6 分钟前
JeeWMS 开源仓库管理系统全景解读:一套 Java WMS 如何把 WMS/OMS/BMS/TMS 装进同一个系统
java·开源
曹牧16 分钟前
Java集合框架:List、ArrayList、Map 和 HashMap
java
顾城猿21 分钟前
STOMP 协议
java
郑州光合科技余经理43 分钟前
同城外卖小程序开发:下单成功后,后台导出能不能对上用户端状态
开发语言·前端·git·后端·uni-app·php·ai编程
知识分享小能手1 小时前
C++ 学习教程,从入门到精通,C++ 入门知识 — 完整知识点(1)
开发语言·c++·学习
+VX:Fegn08951 小时前
计算机毕业设计|基于springboot + vue旅游管理系统(源码+数据库+文档)
java·开发语言·vue.js·spring boot·课程设计
需要8262 小时前
MySQL 索引 B+ 树与“查询为什么变慢了
java·spring boot·spring·spring cloud·tomcat
一 乐2 小时前
二手交易平台|基于springboot + vue二手交易平台(源码+数据库+文档)
java·数据库·vue.js·spring boot·小程序
万年咸鱼2 小时前
编译Java源程序
java
Wang's Blog2 小时前
Java 项目实战: 外卖平台-删除分类的关联校验与自定义业务异常
java·服务器·项目开发