猿问

使用@Async注解限制线程数并等待最大线程数

我将 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 与特定大小的固定线程池一起使用,这会实现吗?


慕工程0101907
浏览 574回答 2
2回答

侃侃尔雅

我想限制可能的线程数,同时不丢失任何消息。我的这个要求没有从现有的答案中得到满足,我找到了另一种方法来做到这一点。因此,将其发布为答案:我制作了一个 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 个线程很忙时,我的调用者线程将执行任务,并且由于我的调用者线程在异步函数中,它不会执行任何新任务。因此,我不会在不增加队列大小的情况下放弃我的任务。

慕哥9229398

根据 ThreadPoolExecutor 的工作原理,第 11 个任务将被拒绝,因为当队列已满时,执行程序会尝试增加池大小,如果由于达到最大值而无法执行,则会拒绝该任务。您可以在 Spring 文档中找到相关信息:主要思想是,当提交任务时,如果当前活动线程数小于核心大小,则执行程序首先尝试使用空闲线程。如果已达到核心大小,则将任务添加到队列中,只要其容量尚未达到。只有这样,如果队列的容量已经达到,执行程序才会创建一个超出核心大小的新线程。如果也达到了最大大小,则执行者拒绝该任务。关于您的要求:我的要求是不要执行使用@Async 方法生成的固定数量的线程,并在达到最大线程数时让调用者等待。如果我将 ConcurrentTaskExecutor 与特定大小的固定线程池一起使用,这会实现吗?因此,因此增加队列大小并为核心和最大池大小保留相同的值。OutOfMemoryError您也可以使用无界队列,它是队列大小参数的默认值,但要小心,因为如果队列中堆积了太多任务 ,可能会导致这种情况。
随时随地看视频慕课网APP

相关分类

Java
我要回答