我正在将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批注的方法,并且假设它已被调用2次,并且2个线程仍在运行。据我了解,对它的任何新调用都将添加到容量为10的队列中。现在,如果我收到第11个任务,它的行为是什么?它会拒绝这里所述的任务吗:https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html?还是呼叫者会等待队列插槽变空?
我的要求是不使用使用@Async方法生成的固定线程数,并且如果达到最大线程数,则使调用方等待。如果我将ConcurrentTaskExecutor与特定大小的固定线程池一起使用,是否可以实现?
答案 0 :(得分:1)
我想限制可能的线程数以及不丢失任何消息。现有的答案未满足我的要求,我找到了另一种方法。因此,将其发布为答案:
我制作了一个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个线程繁忙时,我的调用者线程将执行任务;由于我的调用者线程位于async函数内,因此不会执行任何新任务。因此,在不增加队列大小的情况下,我不会松懈任务。
答案 1 :(得分:0)
根据ThreadPoolExecutor的工作方式,第11个任务将被拒绝,因为当队列已满时,执行器将尝试增加池的大小,并且如果由于达到最大值而无法执行该操作,它将拒绝该任务。 br /> 您可以找到信息there in the Spring documentation:
主要思想是,在提交任务时,执行者首先 如果活动线程数为,则尝试使用空闲线程 目前小于核心大小。如果已达到核心大小, 只要任务的容量尚未添加,就将其添加到队列中 已达成。只有这样,如果队列的容量已达到, 执行程序是否创建超出核心大小的新线程。如果最大 大小也已达到,然后执行者拒绝任务。
关于您的要求:
我的要求是不使用使用生成的固定数量的线程 @Async方法,如果最大线程数是多少,则使调用方等待 到达。如果我将ConcurrentTaskExecutor与 固定大小的固定线程池?
因此,请增加队列大小,并为核心和最大池大小保留相同的值。您还可以使用无界队列,该队列是队列大小参数的默认值,但请注意,因为如果队列中堆叠了太多任务,则可能导致OutOfMemoryError
。