同步任务:
同步任务是在单线程中按顺序执行,每次只有一个任务在执行,不会引发线程安全和数据一致性等
并发问题
同步任务需要等待任务执行完成后才能执行下一个任务,无法同时处理多个任务,响应慢,影响用
户体验
异步任务:
异步任务是在多线程中同时执行,多个任务可以并发执行,同时处理多个请求,响应快,资源利用
率高,用户体验好
异步任务需要创建额外的线程来执行任务操作,可以使用线程池技术,灵活配置线程资源,以提高
系统的资源利用率
应该场景:比如用户的操作日志,我操作完之后还需要去执行日志记录,这个时候如果日志记录比较慢,那么用户就需要一直等待,体验感较差,我们应该开启一个新的线程去执行日志记录,返回给用户操作成功。比较经典应用就是下单。
调用python程序,我这边不可能一直等待python程序调用,给调用的代码加一个异步处理,直接返回给前端调用成功,对于python代码的调用结果可以通过websocket推送到前端去。
springBoot框架使用异步
在启动类上加上注解
@EnableAsync // 启用异步任务支持
在需要异步的方法上面添加注解
@Asyncpublic void print() throws InterruptedException {Thread.sleep(3000);System.out.println("这是执行的异步方法"+System.currentTimeMillis());}
调用异步方法
@Autowired
private testService testService;
@SneakyThrows //这个是抛异常的
@GetMapping("/hello")
public String asny(){System.out.println("hello world");testService.print();return "hello"+System.currentTimeMillis();
}
注意异步方法不能和调用的方法同一个类中,否则异步不会生效。
使用了异步之后,方法会直接返回,下面的操作会在后面慢慢执行。
- 异步调用必须通过代理: 确保异步方法是在不同的 Spring 管理的 bean 中调用,而不是在同一个类中直接调用。
- 启用异步功能: 在启动类中添加
@EnableAsync
注解,以启用 Spring 的异步功能。
配置自定义线程池
**默认情况下,Spring Boot 使用一个简单的线程池来执行异步任务。如果你需要更复杂的配置,例如增加线程池大小或设置线程名称前缀,可以自定义 **Executor**
。 **
package com.njitzx.config;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 //交给spring容器管理
public class AsyncConfig implements AsyncConfigurer {@Bean(name = "asyncExecutor")public Executor asyncExecutor() {// 定义线程池,使用Spring提供的ThreadPoolTaskExecutorThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10); // 核心线程数executor.setMaxPoolSize(20); // 最大线程数executor.setQueueCapacity(50); // 缓冲队列大小executor.setKeepAliveSeconds(60); // 线程的空闲时间executor.setThreadNamePrefix("AsyncTaskExecutor-"); // 线程前缀executor.setRejectedExecutionHandler(newThreadPoolExecutor.CallerRunsPolicy()); // 拒绝处理策略,交由调用方线程运行executor.initialize(); // 初始化return executor;}@Overridepublic Executor getAsyncExecutor() {return asyncExecutor();}
}