5

SpringBoot异步注释@Async的并发陷阱

 1 year ago
source link: https://www.jdon.com/62586
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

SpringBoot异步注释@Async的并发陷阱


在 Java 并发编程中实现异步函数之前,一般需要使用线程或线程池。
线程池的底层也使用线程。
要实现一个线程,要么继承Thread类,要么实现Runnable接口,然后在run方法中编写具体的业务逻辑代码。

Spring开发者为了简化这种异步操作,已经帮我们封装了异步功能。
Spring提供了@Async注解,通过它我们可以开启异步功能,使用起来非常方便。

1、将@EnableAsync注解添加到SpringBoot

.

@EnableAsync
@SpringBootApplication
public class Application {

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

2 、在需要进行异步调用的业务方法中添加注解@Async。

@Service
public class CategoryService {

     @Async
     public void add(Category category) {
        // add category
     }
}

3、在方法中调用该业务controller方法。

@RestController
@RequestMapping("/category")
public class CategoryController {

     @Autowired
     private CategoryService categoryService;
  
     @PostMapping("/add")
     public void add(@RequestBody category) {
        categoryService.add(category);
     }
}

这将启用异步功能。

这简单吗?
但是有一个坏消息:使用 @Async注解启用的异步函数会调用该类AsyncExecutionAspectSupport的doSubmit方法。
其中会执行:

executor.submit(task);

最终调用下面doExecute方法:

protected void doExecute(Runnable task) {
    Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) : createThread(task));
    thread.start();
}

如果使用@Async注解启用异步功能,这将导致问题,默认情况下,每次都会创建一个新线程。
在高并发场景下,可能会产生大量线程,导致OOM问题。
因此:

@Async在开启异步功能时不要忘记定义线程池。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK