簡體   English   中英

Spring 引導:異步方法未在單獨的線程中運行

[英]Spring Boot: Async method not running in separate Thread

我想在單獨的線程中運行一個方法。 因此我嘗試使用 @Async 但它不起作用。 打印的 output 始終引用相同的線程 ID。

MyApp.java

@SpringBootApplication
@EnableAsync
@EnableConfigurationProperties(ConfigProperties.class)
public class MyApp {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(MyApp.class, args);
    }

    @Bean("threadPoolTaskExecutor")
    public TaskExecutor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(20);
        executor.setMaxPoolSize(1000);
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setThreadNamePrefix("Async-");
        return executor;
    }

}

MyService.java

@Slf4j
@Service
public class MyService implements ISichtServiceBroker {

@Inject
public MyService(Helper helper) {
    this.helper = helper;
}

@Transactional
public void handle(Message message) {
    System.out.println("Execute method synchronously - " + Thread.currentThread().getName());
    handleAsync(message);
}

@Async("threadPoolTaskExecutor")
public void handleAsync(Message message) {
    System.out.println("Execute method asynchronously - " + Thread.currentThread().getName());
}
}
  • Spring 通過創建代理實現@Transactional@Async的預期效果。 因此,當您注入MyService時,您實際上是在注入MyService的代理,該代理包裝了您的原始 class 實例。 因此,如果通過此代理調用 go,那么這些注釋將起作用,如果在沒有代理的情況下直接調用該方法,它將不起作用。

  • 在您的情況下,當您想要ProxyMyService.handle() --> MyService.handle() --> ProxyMyService. handleAsync() -->MyService.handleAsync() ProxyMyService.handle() --> MyService.handle() --> MyService.handleAsync()時,它就像這樣發生ProxyMyService.handle() --> MyService.handle() --> ProxyMyService. handleAsync() -->MyService.handleAsync() ProxyMyService.handle() --> MyService.handle() --> ProxyMyService. handleAsync() -->MyService.handleAsync()

  • 為了實現這一點,您應該創建兩個服務類並將一個方法放在 class 中,將第二種方法放在另一個中

筆記

而且,當您在兩個不同的服務中執行此操作時,即使handleAsync將以事務方式執行,它也不會使用 handleAsync 方法中的事務。 因為事務要在該方法內部傳播,所以它們應該在同一個線程上執行

第一件事: @Async注釋在被 'this' 調用時不起作用 來自官方文檔

對 object 引用的方法調用將是對代理的調用,因此代理將能夠委托與該特定方法調用相關的所有攔截器(建議)。 但是,一旦調用最終到達目標 object(在這種情況下為 SimplePojo 引用),它可能對自身進行的任何方法調用,例如 this.bar() 或 this.foo(),都將針對這個參考,而不是代理

除了@Kavithakaran 提供的答案之外,您的代碼問題是您正在嘗試使用@Async@Transactional 您有一個異步方法從同一個 class 中的事務方法觸發。

當使用@Async注解時,Spring 框架將在@Component的 Spring 代理上使用 AOP(面向方面編程),以將對此方法的調用包裝在 Runnable 中,並將此 Runnable 安排在任務執行器上。 同樣, @Transactional也使用 AOP 和代理。 在通常沒有 Async 的 Transacional 方法中,事務通過調用層次結構從一個 Spring @Component傳播到另一個。

但是就像你的情況一樣,當@Transactional方法調用@Async時,這不會發生,因為異步方法是從同一個class 調用的,它使用同一個線程。 可能是因為 @Async注釋在被 'this' 調用時不起作用 @Async 的行為就像 @Transactional 注釋一樣。

此外,為了使 Spring 管理@Async方法的事務, @Component Component 或方法本身應聲明@Transactional注釋,這樣 Spring 將管理事務,即使方法正在異步執行。所以,就像先前的回答我的建議是將異步方法提取到一個單獨的組件中,使其具有事務性,並在該組件 class 方法上使用 aync 方法。具有異步方法,例如:

@Slf4j
@Transactional
@Component
public class AsyncClass {

  @Async("threadPoolTaskExecutor")
  public void handleAsync(Message message) {
      System.out.println("Execute method asynchronously - " + 
      Thread.currentThread().getName());
  }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM