Java线程池如何实现精准控制每秒API请求

 更新时间:2024年08月22日 15:05:21   作者:promise524  
这篇文章主要介绍了Java线程池如何实现精准控制每秒API请求问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

Java中基于线程池实现指定每秒发送一定数量的API请求,可以使用ScheduledExecutorService来调度任务,同时使用ThreadPoolExecutor来处理并发请求,可以根据实际需求调整每秒请求数量、执行时间、以及线程池大小。

实现思路

1.创建线程池

  • 使用Executors.newScheduledThreadPool()来创建一个调度线程池
  • 并使用Executors.newFixedThreadPool()来创建一个用于发送API请求的线程池

2.调度任务

  • 使用ScheduledExecutorService来按固定速率调度任务。
  • 通过控制任务的频率,可以确保每秒发送指定数量的请求。

3.定义API请求任务

  • 定义一个实现Runnable接口的类
  • 负责执行具体的API请求

4.控制请求速率

  • 使用调度器每秒提交指定数量的任务到线程池中执行。

引入依赖

    <!-- Apache HttpClient -->
    <dependency>
        <groupId>org.apache.httpcomponents.client5</groupId>
        <artifactId>httpclient5</artifactId>
        <version>5.2</version>
    </dependency>

实现代码

import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;

import java.io.IOException;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class ApiRequestScheduler {

    // 定义线程池,用于并发发送API请求
    private final ExecutorService requestExecutor;

    // 定义调度线程池,用于定时调度请求任务
    private final ScheduledExecutorService scheduler;

    // 记录已发送的请求数量
    private final AtomicInteger requestCounter;

    // 每秒发送的请求数量
    private final int requestsPerSecond;

    // Apache HttpClient 实例
    private final CloseableHttpClient httpClient;

    // API 请求的目标URL
    private final String apiUrl;

    // 构造函数,初始化线程池和调度器
    public ApiRequestScheduler(int requestsPerSecond, String apiUrl) {
        this.requestsPerSecond = requestsPerSecond;
        this.requestExecutor = Executors.newFixedThreadPool(requestsPerSecond);
        this.scheduler = Executors.newScheduledThreadPool(1);
        this.requestCounter = new AtomicInteger(0);
        this.httpClient = HttpClients.createDefault();
        this.apiUrl = apiUrl;
    }

    // 开始调度API请求任务
    public void start() {
        // 每秒调度任务,按照每秒发送的请求数量来执行
        scheduler.scheduleAtFixedRate(() -> {
            for (int i = 0; i < requestsPerSecond; i++) {
                requestExecutor.submit(this::sendApiRequest);
            }
        }, 0, 1, TimeUnit.SECONDS);
    }

    // 停止调度和关闭线程池及HttpClient
    public void stop() {
        scheduler.shutdown();
        requestExecutor.shutdown();
        try {
            if (!scheduler.awaitTermination(1, TimeUnit.SECONDS)) {
                scheduler.shutdownNow();
            }
            if (!requestExecutor.awaitTermination(1, TimeUnit.SECONDS)) {
                requestExecutor.shutdownNow();
            }
            httpClient.close();
        } catch (InterruptedException | IOException e) {
            scheduler.shutdownNow();
            requestExecutor.shutdownNow();
            try {
                httpClient.close();
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }

    // 使用Apache HttpClient发送API请求
    private void sendApiRequest() {
        int requestId = requestCounter.incrementAndGet();
        HttpUriRequestBase request = new HttpGet(apiUrl);
        System.out.println("Sending API request #" + requestId);

        try (CloseableHttpResponse response = httpClient.execute(request)) {
            String responseBody = EntityUtils.toString(response.getEntity());
            System.out.println("Request #" + requestId + " completed with status: " + response.getCode() +
                    ", response: " + responseBody);
        } catch (IOException | ParseException e) {
            System.err.println("Request #" + requestId + " failed: " + e.getMessage());
        }
    }

    public static void main(String[] args) {
        // 每秒发送5个API请求,目标URL为http://example.com/api
        ApiRequestScheduler scheduler = new ApiRequestScheduler(5, "http://www.dzy.com/api");

        // 启动调度器
        scheduler.start();

        // 运行10秒后停止调度器
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        // 停止调度器
        scheduler.stop();
    }
}

实现效果

每秒发送指定数量的API请求,使用Apache HttpClient处理HTTP通信,并确保在多线程环境中正确管理资源。

可以根据实际需求调整每秒请求数量、API URL、以及线程池大小。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java中超过long范围的超大整数相加算法详解(面试高频)

    java中超过long范围的超大整数相加算法详解(面试高频)

    这篇文章主要介绍了java中超过long范围的超大整数相加算法(面试高频),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • 浅谈HashMap在高并发下的问题

    浅谈HashMap在高并发下的问题

    这篇文章主要介绍了HashMap在高并发下的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Java实现冒泡排序算法

    Java实现冒泡排序算法

    这篇文章主要为大家详细介绍了java实现冒泡排序算法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • Mybatis查询记录条数的实例代码

    Mybatis查询记录条数的实例代码

    这篇文章主要介绍了Mybatis查询记录条数的实例代码,需要的朋友可以参考下
    2017-08-08
  • SpringBoot2.x中management.security.enabled=false无效的解决

    SpringBoot2.x中management.security.enabled=false无效的解决

    这篇文章主要介绍了SpringBoot2.x中management.security.enabled=false无效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • SpringBoot中集成串口通信的项目实践

    SpringBoot中集成串口通信的项目实践

    本文主要介绍了SpringBoot中集成串口通信,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-08-08
  • Spring IoC容器知识点详解

    Spring IoC容器知识点详解

    在本篇文章里小编给各位整理的是关于Spring IoC容器的相关知识点内容,有需要的朋友们可以学习下。
    2019-09-09
  • SpringCloud Gateway自动装配实现流程详解

    SpringCloud Gateway自动装配实现流程详解

    Spring Cloud Gateway旨在为微服务架构提供一种简单有效的、统一的 API 路由管理方式。Spring Cloud Gateway 作为 Spring Cloud 生态系中的网关,它不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全、监控/埋点和限流等
    2022-10-10
  • Java在PDF中替换文字详解及可能遇到的问题

    Java在PDF中替换文字详解及可能遇到的问题

    本文详细介绍了如何使用Java和Spire.PDF for Java库在PDF文档中批量替换文字,包括替换特定文字的所有实例、第一个实例以及使用正则表达式,同时,探讨了可能遇到的问题及其解决方案,需要的朋友可以参考下
    2024-09-09
  • Spring框架AOP基础之代理模式详解

    Spring框架AOP基础之代理模式详解

    代理模式(Proxy Parttern)为一个对象提供一个替身,来控制这个对象的访问,即通过代理对象来访问目标对象。本文将通过示例详细讲解一下这个模式,需要的可以参考一下
    2022-11-11

最新评论