限流之漏桶算法

java 复制代码
package com.gewb.test;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: James.Ge
 * @Date: 2025/12/28
 * @Description 漏桶算法
 */
public class LeakyBucketRateLimiter {
    /**
     * 漏桶容量
     */
    private final int bucketCapacity;

    /**
     * 请求处理速率
     */
    private final int consumeRate;

    /**
     * 请求队列
     */
    private final BlockingQueue<Runnable> bucket;

    private final ScheduledExecutorService executorService;

    public LeakyBucketRateLimiter(int bucketCapacity, int consumeRate) {
        this.bucketCapacity = bucketCapacity;
        this.consumeRate = consumeRate;
        this.bucket = new LinkedBlockingQueue<>(bucketCapacity);
        this.executorService = Executors.newScheduledThreadPool(1);
        // 启动定期消费请求的线程
        startConsuming();
    }

    private void startConsuming() {
//        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
        executorService.scheduleAtFixedRate(() -> {
            for (int i = 0; i < consumeRate; i++) {
                Runnable poll = bucket.poll();
                if(poll != null) {
                    poll.run();
                }
            }
        }, 0, 1, TimeUnit.SECONDS);
    }

    public boolean addRequest(Runnable request) {
        if(bucket.offer(request)) {
            System.out.println("请求已经添加到桶");
            return true;
        } else {
            System.out.println("请求被丢弃,桶已满");
            return false;
        }
    }

    /**
     * 关闭限流器,释放资源
     */
    public void shutdown() {
        while(!bucket.isEmpty()) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        executorService.shutdown();

            // 在异常时可保证能够正常释放资源
//            if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {
//                executorService.shutdownNow();
//            }
//        } catch (InterruptedException e) {
//            executorService.shutdownNow();
//            Thread.currentThread().interrupt();
//        }
        }


        public static void main(String[] args) {
        LeakyBucketRateLimiter rateLimiter = new LeakyBucketRateLimiter(5, 2);
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            rateLimiter.addRequest(() -> {
                LocalDateTime now = LocalDateTime.now();
                String format = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
                System.out.println("处理第" + finalI + "个请求:" + format);
            });
        }

//        try {
//            Thread.sleep(5000);
//        } catch (InterruptedException e) {
//            Thread.currentThread().interrupt();
//        }
        rateLimiter.shutdown();
        System.out.println("程序结束");
    }
}

运行结果:

"C:\Program Files\Java\jdk-17\bin\java.exe" "-javaagent:D:\JetBrains\IntelliJ IDEA 2023.1.2\lib\idea_rt.jar=63321:D:\JetBrains\IntelliJ IDEA 2023.1.2\bin" -Dfile.encoding=UTF-8 -classpath D:\ideaWorkspace2023.1\jdk17\out\production\jdk17;D:\ideaWorkspace2023.1\jdk17\lib\caffeine-3.2.0.jar;D:\ideaWorkspace2023.1\jdk17\lib\jspecify-1.0.0.jar;D:\ideaWorkspace2023.1\jdk17\lib\error_prone_annotations-2.36.0.jar com.gewb.test.LeakyBucketRateLimiter

请求已经添加到桶

请求已经添加到桶

请求已经添加到桶

请求已经添加到桶

请求已经添加到桶

请求已经添加到桶

请求被丢弃,桶已满

请求被丢弃,桶已满

请求被丢弃,桶已满

请求被丢弃,桶已满

处理第0个请求:2025-12-29 11:37:58.659

处理第1个请求:2025-12-29 11:37:58.680

处理第2个请求:2025-12-29 11:37:59.664

处理第3个请求:2025-12-29 11:37:59.664

处理第4个请求:2025-12-29 11:38:00.662

处理第5个请求:2025-12-29 11:38:00.662

程序结束

Process finished with exit code 0

相关推荐
计算机毕设定制辅导-无忧学长9 分钟前
《基于SpringBoot的庭院玫瑰栽培养护知识交互式科普平台设计与实现》
java·spring boot·后端·毕业设计·个性化推荐·协同过滤算法·庭院玫瑰栽培养护知识科普平台
坚定学代码32 分钟前
static在c++中的使用
开发语言·c++
hansang_IR1 小时前
【题解】P5364 [SNOI2017] 礼物
c++·线性代数·算法
Tisfy1 小时前
LeetCode 3871.统计范围内的逗号 II:每次算一个逗号
数学·算法·leetcode·题解
小O的算法实验室1 小时前
IEEE TEVC,基于K-means与DQN辅助元启发式算法的多目标两栖无人艇调度模型
算法·kmeans·启发式算法
Json____1 小时前
从零构建家政服务平台:一套全栈架构如何打通管理端与移动端-java-springboot
java·spring boot·后端·架构·毕设·wwwoop.com
mmmmath_31 小时前
LeetCode.350.两个数组的交集II
算法
Ivanqhz1 小时前
图是“拓扑 + 类型 + 形状“的世界
算法·决策树·机器学习·php·集成学习
云雀衔光1 小时前
Java Spring AI MCP:在 Spring 里把 AI 接上你的业务系统
java·开发语言·人工智能·后端·测试工具·spring
重生之小比特1 小时前
【Java SE】数据类型与变量
java·开发语言·python