java 实现限流器,可用于Rest接口请求处理 | Java工具类

简介: java 实现限流器,可用于Rest接口请求处理 | Java工具类

前言

在工作中是否会碰到这样的场景,高并发的请求但是无法全部执行,需要一定的限流。如果你是使用的微服务框架,比如SpringCloud,可以使用Gateway增加限流策略来解决。本篇文章是在没有框架的情况实现限流器

Maven依赖

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>31.0.1-jre</version>
        </dependency>

代码

上代码,不废话。

首先是限流器代码。

package com.huyi.csdn.tools.rate;
import com.google.common.util.concurrent.Monitor;
import com.google.common.util.concurrent.RateLimiter;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Consumer;
/**
 * @Program: csdn @ClassName: RequestRateLimiter @Author: huyi @Date: 2021-10-30 22:16 @Description:
 * 请求限流器 @Version: V1.0
 */
public class RequestRateLimiter {
  // 请求队列
  private final ConcurrentLinkedQueue<Request> bucket = new ConcurrentLinkedQueue<>();
  // 队列上限
  private static final int BUCKET_CAPACITY = 100;
  // 漏桶下沿水流速度
  private final RateLimiter rateLimiter = RateLimiter.create(10.0D);
  // 请求监视器
  private final Monitor requestMoniter = new Monitor();
  // 处理监视器
  private final Monitor handleMoniter = new Monitor();
  /** 请求实体 */
  public static class Request {
    private int data;
    public Request(int data) {
      this.data = data;
    }
    @Override
    public String toString() {
      return "Request{" + "data=" + data + '}';
    }
  }
  public void submitRequest(int data) {
    this.submitRequest(new Request(data));
  }
  public void submitRequest(Request request) {
    // 请求监视器,创建监视向导,队列数据量小于上限
    if (requestMoniter.enterIf(requestMoniter.newGuard(() -> bucket.size() < BUCKET_CAPACITY))) {
      try {
        boolean result = bucket.offer(request);
        if (result) {
          System.out.println("成功向队列加入新的请求!" + Thread.currentThread() + " request:" + request);
        } else {
          System.out.println("加入新请求失败!");
        }
      } finally {
        requestMoniter.leave();
      }
    } else {
      // 队列已满
      // System.out.println("请求队列已经上限,请稍后重试!");
    }
  }
  // 处理请求方法
  public void handleRequest(Consumer<Request> consumer) {
    if (handleMoniter.enterIf(handleMoniter.newGuard(() -> !bucket.isEmpty()))) {
      try {
        // 匀速处理
        rateLimiter.acquire();
        consumer.accept(bucket.poll());
      } finally {
        handleMoniter.leave();
      }
    }
  }
}

代码说明

1、有个长度100的任务队列,增加了监视器。

2、添加了限流器,限流为10。

验证代码

package com.huyi.csdn.tools.rate;
import java.time.LocalTime;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
/**
 * @Program: csdn @ClassName: TestRateLimiter @Author: huyi @Date: 2021-10-30
 * 22:35 @Description: @Version: V1.0
 */
public class TestRateLimiter {
  private static final AtomicInteger DATA = new AtomicInteger(0);
  private static final RequestRateLimiter HANDLE = new RequestRateLimiter();
  public static void main(String[] args) {
    IntStream.range(0, 10)
        .forEach(
            (x) ->
                new Thread(
                        () -> {
                          while (true) {
                            HANDLE.submitRequest(DATA.getAndIncrement());
                            try {
                              TimeUnit.MILLISECONDS.sleep(100);
                            } catch (InterruptedException e) {
                              e.printStackTrace();
                            }
                          }
                        })
                    .start());
    IntStream.range(0, 20)
        .forEach(
            (x) ->
                new Thread(
                        () -> {
                          while (true) {
                            HANDLE.handleRequest(
                                y ->
                                    System.out.println(
                                        LocalTime.now() + ":处理数据 -> " + y.toString()));
                          }
                        })
                    .start());
  }
}

验证执行结果

image.png

总结

胸中一点浩然气,天地千里快哉风。

如果本文对你有用的,请不要吝啬你的赞,谢谢支持。

相关文章
|
3天前
|
Java
Java抽象类与接口的技术性文章
Java抽象类与接口的技术性文章
11 1
|
3天前
|
Java
Java语言接口(Interface)的深入解析
Java语言接口(Interface)的深入解析
|
3天前
|
缓存 安全 Java
Java的线程池与并发工具类技术性文章
Java的线程池与并发工具类技术性文章
10 0
|
3天前
|
存储 安全 Java
Java的Map接口及其实现类的技术性文章
Java的Map接口及其实现类的技术性文章
6 0
|
3天前
|
存储 安全 Java
Java的List、Set、Queue等接口及其实现类的技术性文章
Java的List、Set、Queue等接口及其实现类的技术性文章
8 1
|
3天前
|
Java API
Java的Lambda表达式与函数式接口的技术性文章
Java的Lambda表达式与函数式接口的技术性文章
6 0
|
4天前
|
Java 编译器
Java 8新特性之Lambda表达式与函数式接口
【5月更文挑战第30天】本文将介绍Java 8中的一个重要新特性——Lambda表达式,以及与之密切相关的函数式接口。我们将通过实例分析Lambda表达式的语法、使用方法和优势,同时探讨函数式接口的定义和应用。通过本文的学习,你将能够更好地理解和运用Java 8的这一新特性,提高编程效率和代码可读性。
|
4天前
|
Java
Java的接口与抽象类的区别
Java的接口与抽象类的区别
|
4天前
|
存储 安全 Java
Java list set map等接口及其实现类
Java list set map等接口及其实现类
|
6天前
|
Java 程序员
Java中的多线程编程:理解并应用Thread类和Runnable接口
【5月更文挑战第28天】在Java中,多线程编程是一个重要的概念,它允许同时执行多个任务。本文将深入探讨Java的多线程编程,包括Thread类和Runnable接口的使用,以及如何在实际项目中应用这些知识。我们将通过实例来理解这些概念,并讨论多线程编程的优点和可能的挑战。