限制线程数,并等待是否使用@Async注释达到最大线程数

时间:2019-05-07 08:11:48

标签: java multithreading spring-boot threadpoolexecutor

我正在将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与特定大小的固定线程池一起使用,是否可以实现?

2 个答案:

答案 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