之前在java并发编程中实现异步功能,一般是需要使用线程或者线程池。
线程池的底层也是用的线程。
而实现一个线程,要么继承Thread类,要么实现Runnable接口,然后在run方法中写具体的业务逻辑代码。
开发spring的大神们,为了简化这类异步操作,已经帮我们把异步功能封装好了。spring中提供了@Async注解,我们可以通过它即可开启异步功能,使用起来非常方便。
具体做法如下:
1.在springboot的启动类上面加上@EnableAsync注解。
@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) {
//添加分类
}
}
3.在controller方法中调用这个业务方法。
@RestController
@RequestMapping("/category")
public class CategoryController {
@Autowired
private CategoryService categoryService;
@PostMapping("/add")
public void add(@RequestBody category) {
categoryService.add(category);
}
}
这样就能开启异步功能了。
是不是很easy?
**但有个坏消息是:**用@Async注解开启的异步功能,会调用AsyncExecutionAspectSupport类的doSubmit方法。
默认情况会走else逻辑。
而else的逻辑最终会调用doExecute方法:
protected void doExecute(Runnable task) {
Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) : createThread(task));
thread.start();
}
我去,这不是每次都会创建一个新线程吗?
没错,使用@Async注解开启的异步功能,默认情况下,每次都会创建一个新线程。
如果在高并发的场景下,可能会产生大量的线程,从而导致OOM问题。
!!!!!!!!!!!!!!!!!!!!!!!
建议大家在@Async注解开启的异步功能时,请别忘了定义一个线程池。