java - 具有每个请求配额的线程池执行器?

标签 java multithreading threadpoolexecutor

我有一个 Web 应用程序,其中一个请求可能会调用多个作业,这些作业必须并行运行。作业涉及通过网络进行的通信,因此它们并不完全受 CPU 限制;此类作业的预计持续时间在几秒到几分钟之间。

显而易见的解决方案是将作业执行委托(delegate)给专用线程池。然而,我想避免出现这样的情况:一个客户端(即一个请求)占用了大部分池来完成自己的工作,而没有给其他客户端留下任何东西。同时,创造就业机会的请求不应受到阻碍;它应该提交其作业以供执行并立即返回。本质上,我正在寻找的是能够根据某些自定义标准设置配额,这样,例如,同时运行的匹配作业不会超过 20 个,即使更多作业已提交到线程池。也许有什么开箱即用的东西吗?

当然,另一种选择是为每个请求创建一个新的固定线程池实例,向其提交作业然后关闭,但感觉这不是正确的方法。

最佳答案

我想不出任何现成的东西。然而,前段时间我已经实现了一个解决类似问题的解决方案,可以进行调整。

举个例子,假设您想要一个总共有 200 个可用线程的线程池,但您只想允许 10 个线程使用单个标识符(在您的情况下:request-id)。

您可以做的是创建 20 个独立的线程池,每个线程池有 10 个线程。然后使用一些简单的逻辑将任务转发到这些线程池之一。它可以基于 hash-of-task-id%number-of-threadpools 来完成。

这将保证来自一个请求(或至少具有相同请求 ID)的所有任务都将转到一个特定的执行程序。

当然这里有一些假设(即你的 id 的哈希值必须分布良好,这样当你得到它的模数时,它会在线程池中均匀地分布 id)和风险(即来自多个请求的任务可能会被分配)到一个池,而其他池可能是空的)。

如果您需要更通用的解决方案,那么恐怕需要更多的实现。

这是上述解决方案的代码:

public class IdAffiliatiedThreadPool {

    private final int executorsCnt;
    private final ExecutorService[] executors;
    
    public IdAffiliatiedThreadPool(String name, int executorsCnt, int threadsPerExecutor) {
        this.executorsCnt = executorsCnt;
        this.executors = new ExecutorService[executorsCnt];
        
        for(int i = 0; i < executorsCnt; i++) {
            this.executors[i] = Executors.newFixedThreadPool(threadsPerExecutor);
        }
    }
    
    public void execute(Object id, Runnable action) {
        int threadId = id.hashCode() % executorsCnt;
        this.executors[threadId].execute(action);
    }
}

关于java - 具有每个请求配额的线程池执行器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69990011/

相关文章:

java - 线程 "main"中出现异常 - 无法获取带有测试用例的类作为 java 应用程序或调试器运行

java - 安卓并行(simultaneous)图片下载

java - 如果 MaximumPoolSize 小于 corePoolSize 该怎么办? Java 6 中可能存在错误吗?

Java Threadpool TCP 服务器(端口不断变化!!)

java - 使用 Java Spring Boot 获取 Json 项目的值

java - 在 Lucene 中将数字与字母分开

node.js - 工作线程在第一条消息后不会响应?

c++ - 如何访问lambda函数中的变量? (c++)

c++ - 等待多个线程通知的条件变量的正确方法

java - ThreadPoolExcutor 和 invokeAll 列表顺序