Kew*_*hka 5 asynchronous spring-boot
我想在单独的线程中运行一个方法。因此我尝试使用@Async但它不起作用。打印输出始终引用相同的线程 ID。
我的应用程序.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;
}
}
Run Code Online (Sandbox Code Playgroud)
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());
}
}
Run Code Online (Sandbox Code Playgroud)
@TransactionalSpring通过创建代理来达到预期的效果 @Async。因此,当您注入时MyService,您实际上是在注入一个MyService包装原始类实例的代理。因此,如果调用通过此代理,那么这些注释将起作用,而如果在没有代理的情况下直接调用该方法,则它将不起作用。
ProxyMyService.handle() --> MyService.handle() --> MyService.handleAsync() 就你而言,当你想要的时候它就会这样发生ProxyMyService.handle() --> MyService.handle() --> ProxyMyService. handleAsync() -->MyService.handleAsync()
为了实现这一目标,您应该创建两个服务类,并将一个方法放在类中,将第二种方法放在另一个类中
笔记
而且,当您在两个不同的服务中执行此操作时,即使handleAsync将以事务方式执行,它也不会使用 handleAsync 方法内的事务。由于事务要在该方法内传播,因此它们应该在同一线程上执行
第一件事:@Async 如果注释由 \xe2\x80\x98this\xe2\x80\x99 调用,则注释不起作用。来自官方文档:
\n\n对该对象引用的方法调用将是对代理的调用,因此代理将能够委托给与该特定方法调用相关的所有拦截器(建议)。然而,一旦调用最终到达目标对象,在本例中是 SimplePojo 引用,它可能对自身进行的任何方法调用,例如 this.bar() 或 this.foo(),都将被\n针对 this 引用而不是代理调用
\n
添加@Kavithakaran 提供的答案,您的代码的问题是您正在尝试使用@Async和@Transactional。您有一个从同一类中的事务方法触发的异步方法。
当使用@Async注释时,Spring 框架将在 Spring 代理上使用 AOP(面向方面编程),@Component将此方法的调用包装在 Runnable 中,并将此 Runnable 调度到任务执行器上。同样,@Transactional也使用AOP和代理。在通常没有异步的事务方法中,事务通过调用层次结构从一个 Spring 传播@Component到另一个 Spring。
但是就像您的情况一样,当一个@Transactional方法调用一个方法时@Async,这种情况不会发生,因为异步方法是从同一个类调用的,它使用相同的线程。可能是因为 @Async注释如果由 \xe2\x80\x98this\xe2\x80\x99 调用则不起作用。@Async 的行为就像 @Transactional 注释。
另外,为了使 Spring 管理方法的事务@Async,或者@Component方法本身应该声明注释@Transactional,这样即使方法正在异步执行,Spring 也会管理事务。所以,就像前面的答案一样,我的建议是将异步方法提取到单独的组件中,使其成为事务性的,并在该组件类方法上使用 aync 方法。有异步方法,例如:
@Slf4j\n@Transactional\n@Component\npublic class AsyncClass {\n\n @Async("threadPoolTaskExecutor")\n public void handleAsync(Message message) {\n System.out.println("Execute method asynchronously - " + \n Thread.currentThread().getName());\n }\n\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
9448 次 |
| 最近记录: |