Java Spring 中受控的 ThreadPoolExecutor

Controlled ThreadPoolExecutor in Java Spring

我需要在我的 Spring 应用程序中创建一个全局 ThreadPoolTask​​Executor,它将负责我应用程序中的 运行 多线程任务。

但是,对于每个请求,我都想限制从该全局线程池中使用的线程数。我应该如何确保根据请求执行此限制?

例如

我创建了一个最大池大小为 50 个线程的全局线程池。但我想将每个请求的线程数限制为 5 个线程。但是这5个线程只能从配置文件中定义的全局线程池中可用的50个线程中分配。

创建任务执行器的配置class。

@Configuration
public class ThreadPoolConfiguration {

    @Value("${threadpool.corepoolsize}")
    int corePoolSize;

    @Value("${threadpool.maxpoolsize}")
    int maxPoolSize;

    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
        pool.setCorePoolSize(corePoolSize);
        pool.setMaxPoolSize(maxPoolSize);
        pool.setWaitForTasksToCompleteOnShutdown(true);
        return pool;
    }
}

控制器class

@RestController
public class WebController {

    @Autowired
    ThreadPoolTaskExecutor threadPool;

    @RequestMapping("/process")
    public String process(){

        String msg = "";
        List<Future<String>> futureList = new ArrayList<>();
        for(int threadNumber = 0; threadNumber < 5; threadNumber ++){
            CallableWorker callableTask = new CallableWorker(String.valueOf(threadNumber));
            Future<String> result = threadPool.submit(callableTask);
            futureList.add(result);
        }

        for(Future<String> future: futureList){
            try {
                msg += future.get() + "#####";
            } catch (Exception e){}
        }

        return msg;
    }
}

免责声明:这只是我从 blog post.

获得的示例代码

如何实现这样的设计?我没有看到任何可以创建的子线程池。我也不想为每个请求实例化一个线程池,因为那将是灾难性的。

有什么建议吗?

解决此问题的一种方法是创建可调用方法来处理元素列表而不是单个元素。

例如,如果您想要删除请求中的 x 个项目,您可以创建 x/5 个元素的列表并将此列表传递给您的可调用函数。这样,通过代码,您可以确保每个请求最多只使用 5 个线程。不过,您必须小心处理异常情况。 (例如,您可以 return elementID 到结果枚举的映射,其中结果可以是成功、可重试异常或不可重试异常。)

此方法可能因您要实现的具体目标而异。

我这样做的方法是创建一个 class 来限制任务。每个请求都会创建一个节流阀并将其所有任务提交给节流阀; throttle 会将前 5 个(比如)任务提交给 Executor,并将其他任务放在列表中。提交的任务完成后,可以提交其他任务。

为了确定任务何时完成,节流器可以定期轮询提交的任务,检查 Future 的 isDone() 方法以查看它们是否已完成,或者它可以阻止一个 Future 的 get() 方法直到它已完成并在此时检查其他未决期货,或者如果您想变得复杂,请求线程可以在节流阀上等待()并且可以将任务设置为在完成时通知()节流阀以便请求线程然后会醒来并检查已完成的任务。