Java Spring中受控的ThreadPoolExecutor

时间:2017-09-04 16:44:49

标签: java spring multithreading threadpool threadpoolexecutor

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

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

例如。

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

用于创建任务执行程序的配置类。

@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;
    }
}

控制器类

@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获得的示例代码。

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

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

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

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

这种方法可能会有所不同,具体取决于您想要达到的目标。

答案 1 :(得分:0)

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

要确定任务何时完成,油门可以定期轮询提交的任务,检查期货&#39; isDone()方法查看它们是否已完成,或者它可以阻止一个Future的get()方法,直到它完成并检查其他待处理的期货,或者如果你想变得复杂,请求线程可以在节流上等待(),并且可以设置任务以在完成时通知()节流,这样请求线程将被唤醒并检查已完成的任务。