提问者:小点点

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


我正在spring-boot 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();
}

我的<code>TestAsyncClass</code>:

public class TestAsyncClazz {

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

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

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

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


共1个答案

匿名用户

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

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

如果您这样做,Spring就没有机会使用必要的代理类来装饰实例,该代理类提供了异步运行方法的实际功能。

这只会以您在Springbeans上期望的方式工作——换句话说,不要自己实例化TestAsyncClazz;定义类的Springbean实例,将该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();
    }
}