异步多线程
提前了解
- 一个HTTP请求会对应一个独立的线程,Servlet容器自动管理这些线程
- 数据库连接池是管理连接对象的(强调数据库资源),会被数据库管理系统自动管理;线程池是管理线程对象的(强调操作系统资源)
- 事务强调的是一组操作,不仅仅只用在数据库中,例如@Transaction
什么是异步多线程
说的很顺口,讲起来却傻傻分不清。
- 异步:执行某耗时操作时(文件上传、数据处理、外部服务调用)不用阻塞主线程,而是可以继续执行其他操作。
- 多线程:并行处理不同任务的一种方式
- 两者的关系:异步的实现不一定依赖多线程,但多线程是实现异步的一种方式
故当我们说起异步多线程时,表达的真正含义是使用多线程实现异步操作。
为什么要进行异步操作
- 耗时少:减少阻塞时间,提高响应速度,从而提升吞吐量,提升用户体验
- 高并发环境:不用阻塞,减少线程数量,提高系统性能
什么情况下该使用异步操作
- 文件上传下载、数据处理、外部服务调用
- 待补充
多线程编程
线程池管理
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@EnableAsync // 开启异步方法
public class ThreadPoolConfig {
@Bean
public ExecutorService executorService() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
// 设置核心线程数
threadPoolTaskExecutor.setCorePoolSize(16);
// 设置最大线程数
threadPoolTaskExecutor.setMaxPoolSize(16);
// 设置任务队列大小
threadPoolTaskExecutor.setQueueCapacity(2000);
// 设置线程名称前缀
threadPoolTaskExecutor.setThreadNamePrefix("threadPoolTaskExecutor-->");
// 设置拒绝策略.当工作队列已满,线程数为最大线程数的时候,接收新任务交给主线程执行
threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 初始化线程池
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor.getThreadPoolExecutor();
}
}
@Service
public class AsyncServiceImpl implements AsyncService {
@Override
@Async("asyncServiceExecutor") // value参数:指定线程池
public void executeAsync() {
System.out.println("异步线程要做的事情");
}
}
异步处理获取结果
@RestController
public class MyController {
@Autowired
private MyService myService;
@GetMapping("/test-async")
public String testAsync() throws InterruptedException, ExecutionException {
// 调用异步方法
CompletableFuture<String> future = myService.asyncMethod();
// 等待异步任务完成并获取结果
String result = future.get(); // 阻塞等待结果
return result;
}
}
线程安全
public class Ticket implements Runnable {
private final Lock lock = new ReentrantLock();
private int tickets = 100;
@Override
public void run() {
while (true) {
// 加锁
this.lock.lock();
try {
if (this.tickets > 0) {
System.out.println(Thread.currentThread().getName() + "卖第" + this.tickets-- + "张票");
}
} finally {
// 释放锁
this.lock.unlock();
}
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
2024-01-03 redis容器docker-compose启动正常,但配置文件无法生效
2024-01-03 Redis过期回调机制
2023-01-03 Navicat破解
2023-01-03 将一台服务器上的数据库迁移到另一台服务器上