简易限流实现

需求描述

写一个1秒两个的限流工具类,2r/s

使用semaphore

代码实现-类似令牌桶算法


public class LimitHelper {

    private int maxLimit;

    private Semaphore semaphore;

    private int timeoutSeconds;

    public LimitHelper(int maxLimit, int timeoutSeconds) {
        this.maxLimit = maxLimit;
        semaphore = new Semaphore(maxLimit);
        this.timeoutSeconds = timeoutSeconds;
        this.autoRelease();
    }

    /**
     * 每秒钟释放两个信号出来
     */
    private void autoRelease() {
        new Thread(() -> {
            try {
                while (true) {
                    TimeUnit.SECONDS.sleep(timeoutSeconds);
                    if (!semaphore.tryAcquire(1)) {
                        // 无信号了
                        semaphore.release(maxLimit);
                    }else {
                        // 池中有信号,并且消耗了一个,释放一个补偿
                        semaphore.release(1);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }

    public boolean acquire() {
        try {
            return semaphore.tryAcquire(1, timeoutSeconds, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        LimitHelper limitHelper = new LimitHelper(2, 1);
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                while (true) {
                    if (limitHelper.acquire()) {
                        System.out.println( System.currentTimeMillis() / 1000+ "  " + Thread.currentThread().getName() + " 获取到令牌");
                        try {
                            // 业务处理
                            TimeUnit.MILLISECONDS.sleep(20);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    } else {
                        System.out.println(System.currentTimeMillis() / 1000 + "  "+Thread.currentThread().getName() + " 被限流了");
                    }
                }
            }).start();
        }
    }

}

结果演示

滑动窗口算法实现

如上图,红色是被限流的请求事件蓝色是允许的请求事件。

代码实现


public class LimitHelper2 {

    /**
     * 次数
     */
    private int maxRate;

    /**
     * 多久时间内
     */
    private int rangeTimeSeconds;

    /**
     * 历史记录
     */
    private volatile LinkedList<Long> timeRecord;

    public LimitHelper2(int maxRate, int rangeTimeSeconds) {
        this.maxRate = maxRate;
        this.rangeTimeSeconds = rangeTimeSeconds;
        timeRecord = new LinkedList<>();
    }

    /**
     * 2r/s 限流实现
     */
    private synchronized boolean acquire() {

        long now = System.currentTimeMillis();
        long min = now - (rangeTimeSeconds * 1000L);

        if (timeRecord.isEmpty()) {
            timeRecord.addLast(now);
            return true;
        }

        // 不为空并且size >= maxRate
        int count = 0;
        if (timeRecord.size() >= maxRate) {
            LinkedList<Long> newRecords = new LinkedList<>();
            for (int i = 0; i < maxRate; i++) {
                Long beforeHappenTime = timeRecord.pollLast();
                if (beforeHappenTime == null) {
                    timeRecord.addLast(now);
                    System.out.println("before时间为null");
                    return true;
                }
                newRecords.addFirst(beforeHappenTime);
                if (beforeHappenTime.compareTo(min) >= 0) {
                    count++;
                } else {
                    break;
                }
            }
            timeRecord = newRecords;
            if (count >= maxRate) {
                return false;
            } else {
                timeRecord.addLast(now);
                return true;
            }
        } else {
            timeRecord.add(now);
            return true;
        }

    }


    public static void main(String[] args) {
        // 1秒2次 限流
        LimitHelper2 limiter = new LimitHelper2(4, 1);
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                while (true) {
                    if (limiter.acquire()) {
                        try {
                            System.out.println(System.currentTimeMillis() + "  " + Thread.currentThread().getName() + " 执行任务");
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        System.out.println(System.currentTimeMillis() + "  " + Thread.currentThread().getName() + " 被限流");
                    }
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }).start();
        }
    }

}

结果演示

4r/s

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/788238.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OpenAI与Thrive Global推出Thrive AI Health:AI驱动的健康教练应用

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

MMGPL: 多模态医学数据分析与图提示学习| 文献速递-基于深度学习的多模态数据分析与生存分析

Title 题目 MMGPL: Multimodal Medical Data Analysis with Graph Prompt Learning MMGPL: 多模态医学数据分析与图提示学习 01 文献速递介绍 神经学障碍&#xff0c;包括自闭症谱系障碍&#xff08;ASD&#xff09;&#xff08;Lord等&#xff0c;2018年&#xff09;和阿…

虚拟内存【Linux】

虚拟内存 为什么需要虚拟内存Linux虚拟内存的结构32位系统下的虚拟地址空间64位系统下的虚拟地址空间页表多级页表TLB 流程虚拟内存的作用 为什么需要虚拟内存 为了在进行多进程编码进行内存访问的时候保持内存的隔离性&#xff0c;数据安全性&#xff0c;所以出现了虚拟内存。…

PPI(每英寸像素数)、DPI(每英寸点数)和Pixel(像素)的区别和联系?

一、定义 PPI、DPI和Pixel是图像处理、打印和显示领域中常用的三个概念&#xff0c;它们之间既有区别又有联系。以下是对这三个概念进行分别讲解&#xff1a; 1. PPI&#xff08;Pixels Per Inch&#xff09;&#xff0d;即每英寸像素数&#xff0c;是图像分辨率的一种表示方…

(补充):java各种进制和文本、图像、音频在计算机中的存储方式

文章目录 前言一、进制1 逢几进一2 常见进制在java中的表示3 进制中的转换(1)任意进制转十进制(2)十进制转其他进制二、计算机中的存储1 计算机的存储规则(文本数据)(1)ASCII码表(2)编码规则的发展演化2 计算机的存储规则(图片数据)(1)分辨率、像素(2)黑白图与灰度…

科技日报社激发数据要素价值,树立媒体行业数字化转型标杆

更多案例研究与行业报告&#xff0c;请前往爱分析官网 媒体行业企事业单位在数据要素领域得天独厚&#xff0c;日积月累的新闻报道、媒资素材、读者反馈和市场研究&#xff0c;沉淀出属于它们的“数据金矿”。 但是&#xff0c;多数相关单位尚未重视和发挥数据要素价值&#…

LLM应用构建前的非结构化数据处理(三)文档表格的提取

1.学习内容 本节次学习内容来自于吴恩达老师的Preprocessing Unstructured Data for LLM Applications课程&#xff0c;因涉及到非结构化数据的相关处理&#xff0c;遂做学习整理。 本节主要学习pdf中的表格数据处理 2.环境准备 和之前一样&#xff0c;可以参考LLM应用构建前…

车载聚合路由器应用场景分析

乾元通QYT-X1z车载式1U多卡聚合路由器&#xff0c;支持最多8路聚合&#xff0c;无论是应急救援&#xff0c;还是车载交通&#xff0c;任何宽带服务商无法覆盖的区域&#xff0c;聚合路由器可提供现场需要的稳定、流畅、安全的视频传输网络&#xff0c;聚合路由器可无缝接入应急…

Flutter-实现物理小球碰撞效果

效果 引言 在Flutter应用中实现物理动画效果,可以大大提升用户体验。本文将详细介绍如何在Flutter中创建一个模拟物理碰撞的动画小球界面,主要代码实现基于集成sensors_plus插件来获取设备的加速度传感器数据。 准备工作 在开始之前,请确保在pubspec.yaml文件中添加senso…

未羽研发测试管理平台

突然有一些觉悟&#xff0c;程序猿不能只会吭哧吭哧的低头做事&#xff0c;应该学会怎么去展示自己&#xff0c;怎么去宣传自己&#xff0c;怎么把自己想做的事表述清楚。 于是&#xff0c;这两天一直在整理自己的作品&#xff0c;也为接下来的找工作多做点准备。接下来…

rsync远程同步--累了,明天继续再写~。

rsync官网链接 rsync(Remote Sync,远程同步)开源快速备份工具&#xff0c;是一个用于本地和远程文件同步的Unix-like命令行程序。它使用“快速数据传输算法”&#xff0c;只发送源和目标之间的差异&#xff0c;因此数据传输非常高效。 可以在不同主机之间镜像同步整 个目录树…

[安洵杯 2019]easy_serialize_php

源码&#xff1a; <?php$function $_GET[f];function filter($img){$filter_arr array(php,flag,php5,php4,fl1g);$filter /.implode(|,$filter_arr)./i;return preg_replace($filter,,$img); }if($_SESSION){unset($_SESSION); }$_SESSION["user"] guest; …

JRE、JVM、JDK分别是什么。

JDK JDK的英文全称是Java Development Kit。JDK是用于制作程序和Java应用程序的软件开发环境。JDK 是 Java 开发工具包&#xff0c;它是 Java 开发者用来编写、编译、调试和运行 Java 程序的集合。JDK 包括了 Java 编译器&#xff08;javac&#xff09;、Java 运行时环境&…

VUE中ECharts提示框tooltip自动切换

目录 前言1导入插件2定义参数3 插件API 前言 使用VUE开发的数据大屏统计&#xff0c;又需要将 echarts的提示框 tooltip 实现自动切换&#xff0c;网上有个很简单的插件&#xff08;echarts-tooltip-auto-show&#xff09;&#xff0c;使用教程简单分享给大家。 自动每隔几秒切…

LeetCode热题100刷题10:46. 全排列、78. 子集、17. 电话号码的字母组合、39. 组合总和、138. 随机链表的复制

回溯问题 46. 全排列 全排列问题&#xff1a; path 递归终止条件&#xff1a;path中是否已存储所有元素&#xff1b; for循环处理节点集合&#xff1a;used0未被使用的元素 class Solution { public:vector<int> path;vector<vector<int>> res;void backt…

【深度学习基础】MAC pycharm 专业版安装与激活

文章目录 一、pycharm专业版安装二、激活 一、pycharm专业版安装 PyCharm是一款专为Python开发者设计的集成开发环境&#xff08;IDE&#xff09;&#xff0c;旨在帮助用户在使用Python语言开发时提高效率。以下是对PyCharm软件的详细介绍&#xff0c;包括其作用和主要功能&…

『大模型笔记』GraphRAG:用于复杂数据发现的新工具现已在GitHub上发布

GraphRAG:用于复杂数据发现的新工具现已在GitHub上发布 文章目录 一. GraphRAG:用于复杂数据发现的新工具现已在GitHub上发布1. 评估和结果2. 研究见解和未来方向二. 参考文献一. GraphRAG:用于复杂数据发现的新工具现已在GitHub上发布 下载 GraphRAG今年早些时候,我们介绍…

Qt Creator仿Visual Studio黑色主题

转自本人博客&#xff1a;Qt Creator仿Visual Studio黑色主题 1.演示 配置文件和步骤在后面&#xff0c;先看成品&#xff0c;分别是QWidget和QML的代码编写界面&#xff1a; 2. 主题配置文件 下载链接&#xff1a;QtCreator _theme_VS_dark.xml 也可以自己新建一个xml文件&…

【每日一练】python基础入门实例

""" 幼儿园加法练习题 题数不限 每满100分奖励10个棒棒糖 要求&#xff1a; 1.使用三目运算符与基础运算的对比 2.随机数字相加 3.调用函数 4.循环执行练习题 5.有计算分数 6.有时间停止休眠 """ #导入随机模块 import random #导入时间模块 imp…

Data-Juicer:阿里巴巴荣誉出品的大模型数据清洗框架

Diffusion Models专栏文章汇总:入门与实战 前言:如何优雅地进行大规模数据清洗是一门艺术,特别对于大模型,数据的质量是决定模型成功最关键的因素之一。阿里巴巴最近开源了一项专门针对大语言模型和视频生成大模型的数据清洗框架,值得关注! 目录 主要特点 数据处理 分…