Springynot Async метод запускается в том же потоке - PullRequest
0 голосов
/ 24 января 2019

Я тестирую @Async в весенней загрузке 2 и следовал некоторому онлайн-уроку

Мой класс конфигурации:

@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();
}

My 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 голосов
/ 24 января 2019

Это происходит потому, что вы вызываете асинхронный метод для класса, который вы создаете сами, используя new:

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

Если вы сделаете это таким образом, у Spring не будет возможности украсить экземпляр необходимым прокси-классом, который обеспечивает реальную функциональность для асинхронного запуска метода.

Это будет работать только так, как вы ожидаете от бобов Spring - другими словами, не создавайте экземпляр 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();
    }
}
...