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

8

我正在使用Spring的Java配置和AsyncConfigurer:

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

现在假设我有一个带有 @Async 注释的方法,而且它已经被调用了两次,还有两个线程正在运行。据我的理解,任何新的调用都将添加到容量为 10 的队列中。现在,如果我收到第 11 个任务,它会怎么样呢?它会拒绝任务像这里所述吗:https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html?还是调用者要等待队列槽可用?我的要求是不超过使用 @Async 方法产生的固定数量的线程,并且当达到最大线程数时让调用者等待。如果我使用具有特定大小的固定线程池的 ConcurrentTaskExecutor,是否可以实现这一点?
2个回答

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

然后使用

@Async("CustomAsyncExecutor")
public void methodName(){
....
}

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

executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy())

这个方法帮助了我。当我的5个线程都繁忙时,调用者线程将执行任务,由于调用者线程在异步函数内部,它不会接受任何新任务。因此,我可以不增加队列大小而不失去任务。


2
根据ThreadPoolExecutor的工作方式,第11个任务将被拒绝,因为当队列已满时,执行程序会尝试增加池大小,如果无法增加,因为达到了最大值,则拒绝该任务。
您可以在Spring文档中找到相关信息:查看

主要思想是,在提交任务时,如果活动线程数当前小于核心大小,则执行程序首先尝试使用空闲线程。 如果已达到核心大小,则将任务添加到队列中,只要队列容量尚未达到。 然后,仅当队列容量已达到时,执行程序才创建超出核心大小的新线程。 如果还达到了最大大小,则执行程序拒绝该任务。

关于您的需求:

我的要求是不超过使用@Async方法生成的固定线程数,并且在达到最大线程数时使调用者等待。如果我使用具有特定大小的固定线程池的ConcurrentTaskExecutor,这是否可行?

因此,相应地增加队列大小,并保持核心和最大池大小的相同值。 您还可以使用无限制队列,它是队列大小参数的默认值,但请注意,如果队列中堆积了太多任务,可能会导致OutOfMemoryError。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接