使用@Async 注释限制线程数并在达到最大线程数时等待

KCK*_*KCK 5 java multithreading threadpoolexecutor spring-boot

我在 AsyncConfigurer 中使用 Spring 的 Java 配置:

@Configuration
@EnableAsync
public class AppConfig implements AsyncConfigurer {

@Override
public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(2);
        executor.setQueueCapacity(10);
        executor.setThreadNamePrefix("MyExecutor-");
        executor.initialize();
        return executor;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在假设我有一个带有 @Async 注释的方法,并假设它已经被调用了 2 次并且 2 个线程仍在运行。根据我的理解,对它的任何新调用都将添加到容量为 10 的队列中。现在如果我收到第 11 个任务,它的行为会是什么?它会拒绝此处所述的任务:https : //docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html?或者调用者会等待队列槽变空吗?

我的要求是不执行使用 @Async 方法产生的固定线程数,并在达到最大线程数时让调用者等待。如果我将 ConcurrentTaskExecutor 与特定大小的固定线程池一起使用,这会实现吗?

KCK*_*KCK 4

我想限制可能的线程数量,同时不丢失任何消息。现有的答案并没有满足我的这个要求,我找到了另一种方法来做到这一点。因此,将其发布为答案:


我制作了一个Executor Bean,如下:

@Bean(name = "CustomAsyncExecutor")
public Executor customThreadPoolTaskExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(5);
    executor.setMaxPoolSize(5);
    executor.setQueueCapacity(0);
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    executor.setThreadNamePrefix("Async_Thread_");
    executor.setWaitForTasksToCompleteOnShutdown(true);
    executor.initialize();
    return executor;
}
Run Code Online (Sandbox Code Playgroud)

然后使用

@Async("CustomAsyncExecutor")
public void methodName(){
....
}
Run Code Online (Sandbox Code Playgroud)

考虑到当线程繁忙且队列已满时,新任务会被拒绝,

executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy())

帮助我,当我的 5 个线程繁忙时,我的调用程序线程将执行任务,并且由于我的调用程序线程位于异步函数内,因此它不会执行任何新任务。因此,在不增加队列大小的情况下,我不会丢失任务。