在多数的Java项目中,在很多的场景都是用同步的方式去实现模块间的相互调用,在模块调用间可能会造成一些延迟,本篇文章将使用SpringBoot 去实现异步之间的调用,提高系统的并发性能、用户体验。
简单直观:同步任务的执行是顺序的,代码执行的流程清晰明了,易于理解和调试。
避免并发问题:同步任务在单线程中执行,不会引发线程安全和数据一致性等并发问题。每次只有一个任务在执行,避免了竞态条件和资源竞争。
较少的资源消耗:同步任务不需要额外的线程资源来执行,只使用主线程。这样可以减少线程上下文切换的开销,降低系统的资源消耗。
异常处理简单:同步任务中的异常可以直接抛出,易于捕获和处理。可以在代码中使用try-catch语句来捕获异常,进行相应的异常处理逻辑
阻塞主线程:同步任务需要等待任务执行完成后才能继续执行下一个任务,阻塞主线程。如果一个任务执行时间过长,会导致整个系统的响应变慢,影响用户体验。
降低并发性能:由于同步任务需要按顺序执行,无法同时处理多个请求,降低了系统的并发性能和吞吐量。在高并发场景下,可能会导致系统处理能力不足。
响应时间不稳定:同步任务需要等待任务完成才返回结果,如果任务执行时间不可预知或变化较大,会导致响应时间不稳定,难以控制和优化。
潜在的死锁风险:当同步任务中存在资源竞争或循环依赖时,可能会导致死锁的产生。一旦发生死锁,程序无法进行进一步的执行,造成系统无法正常工作
综上所述,同步任务简单直观,避免了并发问题和资源浪费,异常处理方便。但同时会阻塞主线程,降低并发性能,响应时间不稳定,并且潜在的死锁风险
提高系统的并发能力:异步方式将耗时操作从主线程中分离出来,在后台线程中执行,不会阻塞主线程。这样可以同时处理多个请求,提高系统的并发能力和吞吐量。
提升系统的响应速度:由于异步方式不需要等待耗时操作的完成,主线程可以立即响应其他请求。这样可以减少用户等待时间,提升系统的响应速度,改善用户体验。
优化资源利用:异步方式可以在后台线程中执行耗时操作,释放主线程的资源,减少资源浪费。同时,可以根据需求合理调整线程池的大小,灵活配置线程资源,以提高系统的资源利用效率。
简化编程模型:异步方式可以使用简单的注解(如@Async)或异步框架,简化编程模型。开发者不需要手动处理线程的创建、管理和同步等细节,减少开发复杂性
需要额外的线程资源:异步方式需要创建额外的线程来执行耗时操作,增加了系统对线程资源的需求。如果线程资源不合理配置或管理不当,可能会导致性能下降、内存溢出等问题。
可能引入复杂性:异步方式可能引入了代码的复杂性。当异步操作涉及到多个线程之间的协调和通信时,可能需要更复杂的代码逻辑和同步机制,增加了代码维护的难度。
难以处理异常:异步操作的异常处理相对复杂,需要额外的关注和处理。异步方法的异常无法直接抛出到调用方,需要通过回调、Future对象或异步异常处理机制来进行处理。
可能的竞态条件和并发问题:在多线程环境下,异步方式可能出现竞态条件、资源竞争等并发问题,如线程安全性、数据一致性等。开发者需要进行合理的线程同步和数据保护,以避免潜在的问题
异步方式可以提高系统的并发性能、响应速度和资源利用效率,简化编程模型。然而,需要注意线程资源的合理配置和管理,处理异常和并发问题,以保证异步方式的稳定和可靠性
org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-web org.projectlombok lombok org.springframework.boot spring-boot-starter-test test
import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; /** * 提供异步任务的服务类 */ @Service @Slf4j public class executeService { /** * 异步任务:休眠10秒后,输出"已执行" */ @Async // 使用异步任务 public void execute() { try { /* 假定有一个任务需要执行10秒 */ Thread.sleep(10000); } catch (InterruptedException e) { throw new RuntimeException(e); } // 打印日志信息 log.info("任务已执行完成"); } }
import com.hui.service.executeService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @RestController public class UserController { @Resource private executeService wakeService; @GetMapping("/execute") public String isWakeUp() { // 执行任务 wakeService.execute(); return "ok"; } }
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableAsync; @EnableAsync // 启动异步任务注解 @SpringBootApplication public class AsyncApplication { public static void main(String[] args) { SpringApplication.run(AsyncApplication.class, args); } }
访问:http://localhost:8080/execute,当带上@Async 注解后,controller类会直接响应"ok",而不用去等待10秒,再去响应
10秒过后控制台会输出:“任务已执行完成”
启用异步支持:确保在配置类或主启动类上添加 @EnableAsync 注解,以激活 Spring 的异步处理功能
异步方法边界:@Async 注解只能应用在 public 方法上,因为 Spring 使用基于代理的机制,无法拦截非 public 方法的调用。
同时,异步方法不能在同一个类中被调用,否则注解会失效,并报错。