Spring Boot 异步编程深入剖析
1. 异步方法的利用
原理深度解析
Spring Boot 的异步方法基于 Spring 的 AOP(面向切面编程)实现。当在方法上添加 @Async 注解时,Spring 会为该方法地点的类创建一个署理对象。当调用该异步方法时,实际上是调用署理对象的方法,署理对象会将该方法的执行委托给线程池中的一个线程去执行,而调用线程会继续执行后续代码,从而实现异步执行。
更复杂的利用场景
除了返回 CompletableFuture,还可以利用 ListenableFuture(在 Spring 4.0 之前)或无返回值的异步方法。
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.stereotype.Service;
- import org.springframework.util.concurrent.ListenableFuture;
- import org.springframework.util.concurrent.SettableListenableFuture;
- import java.util.concurrent.CompletableFuture;
- @Service
- public class AsyncService {
- // 无返回值的异步方法
- @Async
- public void asyncVoidMethod() {
- try {
- Thread.sleep(2000);
- System.out.println("Async void method completed");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- // 使用 ListenableFuture
- @Async
- public ListenableFuture<String> asyncListenableMethod() {
- SettableListenableFuture<String> future = new SettableListenableFuture<>();
- try {
- Thread.sleep(2000);
- future.set("Async listenable method completed");
- } catch (InterruptedException e) {
- future.setException(e);
- }
- return future;
- }
- }
复制代码 踩坑记录
- 方法调用问题:如果在同一个类中调用自身的异步方法,@Async 注解不会生效。因为 Spring 的 AOP 署理是基于外部调用的,同一个类中的方法调用不会经过署理对象。办理方法是将异步方法提取到另一个服务类中。
- 非常处理问题:无返回值的异步方法中的非常不会被调用者捕获,因为调用者不会等待方法执行完成。可以在异步方法内部举行非常处理,或者利用 CompletableFuture 来捕获非常。
利专心得
- 对于一些耗时的 I/O 操纵(如数据库查询、网络哀求等),利用异步方法可以显著提高应用步伐的响应性能。
- 合理利用 CompletableFuture 可以方便地处理异步使命的效果和非常,同时还可以举行使命的组合和链式调用。
2. 线程池设置
深入明白线程池参数
- 焦点线程数(corePoolSize):线程池保持的最小线程数。当有新使命提交时,如果线程池中的线程数小于焦点线程数,会创建新的线程来执行使命。
- 最大线程数(maxPoolSize):线程池允许的最大线程数。当队列已满且线程数小于最大线程数时,会创建新的线程来执行使命。
- 队列容量(queueCapacity):用于存储等待执行的使命的队列的容量。当线程池中的线程数到达焦点线程数时,新使命会被放入队列中等待执行。
- 线程空闲时间(keepAliveTime):当线程池中的线程数高出焦点线程数时,空闲线程在经过一定时间后会被销毁。
动态调整线程池参数
可以通过编写自定义的线程池管理器来动态调整线程池的参数。
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.scheduling.annotation.AsyncConfigurer;
- import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
- import java.util.concurrent.Executor;
- @Configuration
- public class AsyncConfig implements AsyncConfigurer {
- private ThreadPoolTaskExecutor executor;
- @Override
- @Bean(name = "asyncExecutor")
- public Executor getAsyncExecutor() {
- executor = new ThreadPoolTaskExecutor();
- executor.setCorePoolSize(5);
- executor.setMaxPoolSize(10);
- executor.setQueueCapacity(25);
- executor.setThreadNamePrefix("AsyncThread-");
- executor.initialize();
- return executor;
- }
- public void adjustCorePoolSize(int corePoolSize) {
- executor.setCorePoolSize(corePoolSize);
- executor.initialize();
- }
- }
复制代码 踩坑记录
- 队列容量设置不合理:如果队列容量设置过大,大概会导致大量使命堆积在队列中,从而影响体系的响应性能。如果队列容量设置过小,大概会导致线程池频仍创建新的线程,增长体系的开销。
- 线程池耗尽问题:如果使命提交速率过快,高出了线程池的处理本领,大概会导致线程池耗尽,从而抛出 RejectedExecutionException 非常。可以通过合理设置线程池参数和实现自定义的拒绝策略来办理这个问题。
利专心得
- 根据应用步伐的实际情况合理设置线程池的参数,避免资源浪费和性能瓶颈。
- 定期监控线程池的状态,根据体系的负载情况动态调整线程池的参数。
3. 异步使命的监控与管理
高级监控方法
除了利用 CompletableFuture 来监控使命状态,还可以利用 Spring Boot Actuator 来监控线程池的状态。
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
复制代码 通过访问 /actuator/metrics 端点可以检察线程池的相干指标,如活泼线程数、使命完成数等。
使命链管理
可以利用 CompletableFuture 的 thenApply、thenAccept、thenCompose 等方法来构建使命链,实现复杂的异步使命管理。
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RestController;
- import java.util.concurrent.CompletableFuture;
- @RestController
- public class AsyncController {
- @Autowired
- private AsyncService asyncService;
- @GetMapping("/asyncChain")
- public String asyncChain() {
- CompletableFuture<String> future1 = asyncService.asyncMethod();
- CompletableFuture<String> future2 = future1.thenApply(result -> result + " -> Next step");
- future2.thenAccept(finalResult -> System.out.println(finalResult));
- return "Async chain started";
- }
- }
复制代码 踩坑记录
- 使命链非常处理问题:在使命链中,如果某个使命抛出非常,后续的使命大概会受到影响。可以利用 exceptionally 方法来处理非常,确保使命链的稳定性。
- 内存泄漏问题:如果 CompletableFuture 没有正确处理,大概会导致内存泄漏。比方,如果一个 CompletableFuture 不停处于未完成状态,会占用内存资源。
利专心得
- 利用使命链可以实现复杂的异步业务逻辑,提高代码的可读性和可维护性。
- 及时处理异步使命中的非常,避免非常扩散导致体系崩溃。
通过深入明白 Spring Boot 异步编程的原理和机制,合理设置线程池,以及有效地监控和管理异步使命,可以充分发挥异步编程的上风,提高应用步伐的性能和响应本领。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |