为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕工程0101907 2022-11-10 16:24:39
我将 Spring 的 Java 配置与 AsyncConfigurer 一起使用:@Configuration@EnableAsyncpublic class AppConfig implements AsyncConfigurer {@Overridepublic 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 回答

?
侃侃尔雅

TA贡献1801条经验 获得超16个赞

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


我制作了一个 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 个线程很忙时,我的调用者线程将执行任务,并且由于我的调用者线程在异步函数中,它不会执行任何新任务。因此,我不会在不增加队列大小的情况下放弃我的任务。


查看完整回答
反对 回复 2022-11-10
?
慕哥9229398

TA贡献1877条经验 获得超6个赞

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

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

关于您的要求:

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

因此,因此增加队列大小并为核心和最大池大小保留相同的值。OutOfMemoryError您也可以使用无界队列,它是队列大小参数的默认值,但要小心,因为如果队列中堆积了太多任务 ,可能会导致这种情况。


查看完整回答
反对 回复 2022-11-10
  • 2 回答
  • 0 关注
  • 573 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号