Springboot异步方法在同一线程中运行

时间:2019-01-24 14:03:15

标签: spring-boot asynchronous

我正在春季靴2中测试@Async,并且遵循了一些在线教程

我的配置类:

@Configuration
@EnableAsync
public class AsyncConfig {

    @Bean
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(5);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("Async Process-");
        executor.initialize();
        return executor;
    }
}

我的控制器的片段:

@GetMapping("/test/async")
public void testAsync() {
    System.err.println("Thread in controller: " + Thread.currentThread().getName());
    TestAsyncClazz clazz = new TestAsyncClazz();
    clazz.testAsyncMethod();
}

我的TestAsyncClass

public class TestAsyncClazz {

    @Async
    public void testAsyncMethod(){
        System.err.println("Running async: "+ Thread.currentThread().getName());
    }
}

当我检查打印行时,它表明我的两个方法都在同一线程上运行,并且没有使用threadNamePrefix Async Process-

Thread in controller: http-nio-8080-exec-2
Running async: http-nio-8080-exec-2

我做错了什么?我误会了吗?

1 个答案:

答案 0 :(得分:1)

发生这种情况是因为您正在使用new实例化自己的类上调用async方法:

TestAsyncClazz clazz = new TestAsyncClazz();
clazz.testAsyncMethod();

如果采用这种方式,Spring将没有机会用必要的代理类来装饰实例,该代理类提供了异步运行方法的实际功能。

这只会按照您对Spring bean的预期方式工作-换句话说,不要自己实例化TestAsyncClazz;定义该类的Spring bean实例,将该bean自动装配到控制器中,然后在bean上调用该方法。

示例:

@Configuration
@EnableAsync
public class AsyncConfig {

    @Bean
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(5);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("Async Process-");
        executor.initialize();
        return executor;
    }

    // Define a Spring bean of type TestAsyncClazz
    @Bean
    public TestAsyncClazz testAsyncClazz() {
        return new TestAsyncClazz();
    }
}

@Controller
public class MyController {

    // Inject the bean here
    @Autowired 
    private TestAsyncClazz testAsyncClass;

    @GetMapping("/test/async")
    public void testAsync() {
        System.err.println("Thread in controller: " +
                Thread.currentThread().getName());

        // Use the bean instead of instantiating the class yourself
        testAsyncClass.testAsyncMethod();
    }
}