SpringBoot 实现异步任务
作者:mmseoamin日期:2023-12-11

异步任务

  • 一、使用背景
  • 二、同步任务的优缺点
    • 2.1 优点
    • 2.2 缺点
    • 2.3 总结
    • 三、异步任务的优缺点
      • 3.1 优点
      • 3.2 缺点
      • 3.3 总结
      • 四、Spring Boot 实现异步任务
        • 4.0 项目结构
        • 4.1 pom.xml
        • 4.2 编写service类
        • 4.3 controller类
        • 4.4 SpringBoot 启动类
        • 4.5 测试
        • 五、使用异步任务注意点
          • 5.1 启用异步支持
          • 5.2 异步方法边界

            一、使用背景

            在多数的Java项目中,在很多的场景都是用同步的方式去实现模块间的相互调用,在模块调用间可能会造成一些延迟,本篇文章将使用SpringBoot 去实现异步之间的调用,提高系统的并发性能、用户体验。


            二、同步任务的优缺点

            2.1 优点

            • 简单直观:同步任务的执行是顺序的,代码执行的流程清晰明了,易于理解和调试。

            • 避免并发问题:同步任务在单线程中执行,不会引发线程安全和数据一致性等并发问题。每次只有一个任务在执行,避免了竞态条件和资源竞争。

            • 较少的资源消耗:同步任务不需要额外的线程资源来执行,只使用主线程。这样可以减少线程上下文切换的开销,降低系统的资源消耗。

            • 异常处理简单:同步任务中的异常可以直接抛出,易于捕获和处理。可以在代码中使用try-catch语句来捕获异常,进行相应的异常处理逻辑

              2.2 缺点

              • 阻塞主线程:同步任务需要等待任务执行完成后才能继续执行下一个任务,阻塞主线程。如果一个任务执行时间过长,会导致整个系统的响应变慢,影响用户体验。

              • 降低并发性能:由于同步任务需要按顺序执行,无法同时处理多个请求,降低了系统的并发性能和吞吐量。在高并发场景下,可能会导致系统处理能力不足。

              • 响应时间不稳定:同步任务需要等待任务完成才返回结果,如果任务执行时间不可预知或变化较大,会导致响应时间不稳定,难以控制和优化。

              • 潜在的死锁风险:当同步任务中存在资源竞争或循环依赖时,可能会导致死锁的产生。一旦发生死锁,程序无法进行进一步的执行,造成系统无法正常工作

                2.3 总结

                综上所述,同步任务简单直观,避免了并发问题和资源浪费,异常处理方便。但同时会阻塞主线程,降低并发性能,响应时间不稳定,并且潜在的死锁风险


                三、异步任务的优缺点

                3.1 优点

                • 提高系统的并发能力:异步方式将耗时操作从主线程中分离出来,在后台线程中执行,不会阻塞主线程。这样可以同时处理多个请求,提高系统的并发能力和吞吐量。

                • 提升系统的响应速度:由于异步方式不需要等待耗时操作的完成,主线程可以立即响应其他请求。这样可以减少用户等待时间,提升系统的响应速度,改善用户体验。

                • 优化资源利用:异步方式可以在后台线程中执行耗时操作,释放主线程的资源,减少资源浪费。同时,可以根据需求合理调整线程池的大小,灵活配置线程资源,以提高系统的资源利用效率。

                • 简化编程模型:异步方式可以使用简单的注解(如@Async)或异步框架,简化编程模型。开发者不需要手动处理线程的创建、管理和同步等细节,减少开发复杂性

                  3.2 缺点

                  • 需要额外的线程资源:异步方式需要创建额外的线程来执行耗时操作,增加了系统对线程资源的需求。如果线程资源不合理配置或管理不当,可能会导致性能下降、内存溢出等问题。

                  • 可能引入复杂性:异步方式可能引入了代码的复杂性。当异步操作涉及到多个线程之间的协调和通信时,可能需要更复杂的代码逻辑和同步机制,增加了代码维护的难度。

                  • 难以处理异常:异步操作的异常处理相对复杂,需要额外的关注和处理。异步方法的异常无法直接抛出到调用方,需要通过回调、Future对象或异步异常处理机制来进行处理。

                  • 可能的竞态条件和并发问题:在多线程环境下,异步方式可能出现竞态条件、资源竞争等并发问题,如线程安全性、数据一致性等。开发者需要进行合理的线程同步和数据保护,以避免潜在的问题

                    3.3 总结

                    异步方式可以提高系统的并发性能、响应速度和资源利用效率,简化编程模型。然而,需要注意线程资源的合理配置和管理,处理异常和并发问题,以保证异步方式的稳定和可靠性


                    四、Spring Boot 实现异步任务

                    4.0 项目结构

                    SpringBoot 实现异步任务,在这里插入图片描述,第1张

                    4.1 pom.xml

                    
                    	org.springframework.boot
                    	spring-boot-starter
                    
                    
                    	org.springframework.boot
                    	spring-boot-starter-web
                    
                    
                    	org.projectlombok
                    	lombok
                    
                    
                    	org.springframework.boot
                    	spring-boot-starter-test
                    	test
                    
                    

                    4.2 编写service类

                    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("任务已执行完成");
                        }
                    }
                    

                    4.3 controller类

                    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";
                        }
                    }
                    

                    4.4 SpringBoot 启动类

                    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);
                    	}
                    }
                    

                    4.5 测试

                    访问:http://localhost:8080/execute,当带上@Async 注解后,controller类会直接响应"ok",而不用去等待10秒,再去响应

                    10秒过后控制台会输出:“任务已执行完成”

                    SpringBoot 实现异步任务,在这里插入图片描述,第2张


                    五、使用异步任务注意点

                    5.1 启用异步支持

                    启用异步支持:确保在配置类或主启动类上添加 @EnableAsync 注解,以激活 Spring 的异步处理功能

                    5.2 异步方法边界

                    异步方法边界:@Async 注解只能应用在 public 方法上,因为 Spring 使用基于代理的机制,无法拦截非 public 方法的调用。

                    同时,异步方法不能在同一个类中被调用,否则注解会失效,并报错。