【问题标题】:Spring @Async method within @Async method@Async 方法中的 Spring @Async 方法
【发布时间】:2018-11-09 05:06:03
【问题描述】:

您好,我正在试用 Springs 异步执行器,发现您可以使用 @Async。我想知道是否有可能在@Async 中使用@Async,要求是将任务委托给在第一个@Async 方法中调用的@Async 方法。

例如:一个目录有100个文件,需要创建作业处理5个线程中的20个文件。

【问题讨论】:

    标签: spring multithreading asynchronous threadpool


    【解决方案1】:

    如果两个异步方法定义在两个不同的类中,那么您将能够从第一个异步方法调用第二个异步方法。但是,如果它们都在同一个类中,则第二个方法的执行将在处理第一个方法本身的线程中内联发生。查看this 答案以获取更多详细信息和一些解决方法。

    对于您的具体情况,您可以定义两个线程池执行器,一个用于第一个异步方法,另一个用于第二个异步方法。 @Async 注释有一个 value 参数,您可以将应该使用的线程池执行程序传递给该参数。

    以下是使用两个执行器的示例。

    @SpringBootApplication
    @EnableAspectJAutoProxy
    @EnableAsync
    public class MultipleExecutorsExample {
    
        @Bean
        public ThreadPoolTaskExecutor executor1() {
            ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
            threadPoolTaskExecutor.setCorePoolSize(10);
            threadPoolTaskExecutor.setMaxPoolSize(10);
            threadPoolTaskExecutor.initialize();
            return threadPoolTaskExecutor;
        }
    
        @Bean
        public ThreadPoolTaskExecutor executor2() {
            ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
            threadPoolTaskExecutor.setCorePoolSize(5);
            threadPoolTaskExecutor.setMaxPoolSize(5);
            threadPoolTaskExecutor.initialize();
            return threadPoolTaskExecutor;
        }
    
        public static void main(String[] args) throws BeansException, InterruptedException {
            ConfigurableApplicationContext context = new SpringApplicationBuilder(MultipleExecutorsExample.class)
                    .web(WebApplicationType.NONE).build().run(args);
            context.getBean(Service1.class).execute();
        }
    
    }
    

    Service1 使用第一个异步方法

    @Component
    @Slf4j
    public class Service1 {
    
        @Autowired
        private Service2 service2;
    
        @Async("executor1")
        public void execute() throws InterruptedException {
            log.info("Sleeping for 5 seconds");
            for (int i = 1; i <= 10; i++) {
                service2.execute();
            }
        }
    
    }
    

    Service2 使用第二种异步方法

    @Component
    @Slf4j
    public class Service2 {
    
        @Async("executor2")
        public void execute() throws InterruptedException {
            log.info("Sleeping for 1 seconds");
            Thread.sleep(1000);
        }
    
    }
    

    程序的输出显示两个异步任务正在使用不同的执行器。

    018-05-30 18:44:27.557  INFO 19839 --- [  restartedMain] c.e.demo.tp.MultipleExecutorsExample     : Started MultipleExecutorsExample in 1.926 seconds (JVM running for 2.407)
    2018-05-30 18:44:27.567  INFO 19839 --- [    executor1-1] com.example.demo.tp.Service1             : Sleeping for 5 seconds
    2018-05-30 18:44:27.570  INFO 19839 --- [    executor2-1] com.example.demo.tp.Service2             : Sleeping for 1 seconds
    2018-05-30 18:44:27.570  INFO 19839 --- [    executor2-2] com.example.demo.tp.Service2             : Sleeping for 1 seconds
    2018-05-30 18:44:27.570  INFO 19839 --- [    executor2-5] com.example.demo.tp.Service2             : Sleeping for 1 seconds
    

    【讨论】:

    • Ranjith 谢谢你的回答。我们不能使用一个线程池吗?为什么要配置两个?
    • @StO 是的,您可以为两个异步任务使用相同的线程池。不知何故,我假设您想要两个不同的线程池用于两个异步任务。在某些情况下,我们使用多个线程池(例如:如果您有多个 asyc 任务,例如处理文件、发送电子邮件等,并且您希望单个任务用完池中的所有线程,则可以配置不同的池每个任务)。对于您的用例,我认为单个线程池就足够了。
    • 感谢 Ranjith 的帮助
    猜你喜欢
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-10
    • 2015-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多