feat:增加SpringBoot 线程与事件文档

This commit is contained in:
2026-06-02 19:41:06 +08:00
parent a825ccdadb
commit 845a29f476
7 changed files with 340 additions and 6 deletions

View File

@@ -18,18 +18,19 @@ export const routers = [
{
text: '🍃 SpringBoot',
items: [
{ text: 'Spring IOC简介', link: '/Web/SpringBoot/SpringIOC' },
{ text: 'Spring AOP简介', link: '/Web/SpringBoot/SpringAOP' },
{ text: 'Spring IOC简介', link: '/Web/SpringBoot/Spring-IOC' },
{ text: 'Spring AOP简介', link: '/Web/SpringBoot/Spring-AOP' },
{ text: 'SpringBoot启动流程', link: '/Web/SpringBoot/SpringBoot-Start-Process' },
{ text: 'Spring MVC简介', link: '/Web/SpringBoot/SpringMVC' },
{ text: 'SpringBoot Starter原理', link: '/Web/SpringBoot/SpringBootStarter' },
{ text: 'SpringBoot Bean简介', link: '/Web/SpringBoot/SpringBootBean' },
{ text: 'Spring MVC简介', link: '/Web/SpringBoot/Spring-MVC' },
{ text: 'SpringBoot Starter原理', link: '/Web/SpringBoot/SpringBoot-Starter' },
{ text: 'SpringBoot Bean简介', link: '/Web/SpringBoot/SpringBoot-Bean' },
{ text: 'SpringBoot注解', link: '/Web/SpringBoot/SpringBoot-Annotation' },
{ text: 'SpringBoot3原生镜像', link: '/Web/SpringBoot/SpringBoot3-GraalVM' },
{ text: 'SpringBoot技巧', link: '/Web/SpringBoot/SpringBoot-Skills' },
{ text: 'SpringBoot Common', link: '/Web/SpringBoot/SpringBoot-Common' },
{ text: 'SpringBoot RestClient简介', link: '/Web/SpringBoot/SpringBoot-RestClient' },
{ text: 'SpringBoot Redis简介和使用', link: '/Web/SpringBoot/SpringBoot-Redis' }
{ text: 'SpringBoot Redis简介和使用', link: '/Web/SpringBoot/SpringBoot-Redis' },
{ text: 'SpringBoot 线程与事件', link: '/Web/SpringBoot/SpringBoot-Thread' }
]
},
{

View File

@@ -0,0 +1,333 @@
---
title: SpringBoot 线程与事件
date: 2026-06-02
---
# 一、基本概念
  **进程**:进程是操作系统资源分配的最小单位,每个进程都有独立的内存空间(代码段、数据段、堆、栈),比如打开一个应用程序,就是一个进程。
  **线程**:线程是 CPU 调度的最小单位,线程共享所属进程的内存空间。 比如一个HTTP请求就是一个线程。
  **协程**:协程是 用户态的轻量级“线程”,由程序自己调度,不依赖操作系统,切换成本极低。
  创建线程方法:
```java
// 继承 Thread 不推荐
class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程运行中:" + Thread.currentThread().getName());
}
}
public class Test {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start(); // ✅ 启动线程
}
}
// 实现 Runnable
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("线程运行中:" + Thread.currentThread().getName());
}
}
public class Test2 {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
}
}
// Lambda 写法
Thread t = new Thread(() -> {
System.out.println("Hello Thread");
});
t.start();
// 线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // 核心线程数
4, // 最大线程数
60,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
```
&emsp;&emsp;**SpringBoot线程池**:
```java
// 1. 启动类加上 @EnableAsync 注解
@EnableAsync
@SpringBootApplication
public class Application {
}
// 2. 线程池配置
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(20);
executor.initialize();
return executor;
}
// 3. 调用方法上加上 @Async 注解
@Service
public class OrderService {
@Async
public void createOrder() {
System.out.println(Thread.currentThread().getName());
}
}
```
# 二、案例
&emsp;&emsp;案例:电商秒杀系统。
- 资源竞争:多个用户抢同一件商品(多线程抢锁)。
- 异步解耦:扣减库存后,需要发短信、发优惠券(多线程并行)。
- 系统解耦:订单系统不应依赖短信系统(事件驱动)。
# 二、JDK原生线程通信
- synchronized锁住库存防止超卖。
- wait/notify通知消息线程“库存已扣可以发通知了”。
- Thread+ ExecutorService实现多线程并行发通知。
## 2.1 共享资源
```java
/**
* 商品库存(共享资源)
*/
public class Stock {
// 假设只有 1 件库存
public int count = 1;
// 信号:是否有人下单成功
public volatile boolean ordered = false;
}
```
## 2.2 下单线程
```java
/**
* 用户下单线程
*/
public class OrderWorker extends Thread {
private final Stock stock;
public OrderWorker(Stock stock) {
this.stock = stock;
}
@Override
public void run() {
// 1. 锁住库存,防止超卖
synchronized (stock) {
if (stock.count > 0) {
System.out.println(Thread.currentThread().getName() + " 抢到锁,准备扣库存");
stock.count--;
stock.ordered = true;
System.out.println("库存扣减成功,剩余:" + stock.count);
stock.notifyAll(); // 通知消息线程
} else {
System.out.println(Thread.currentThread().getName() + " 没抢到,库存不足");
}
}
}
}
```
## 2.3 消息分发线程
```java
/**
* 消息分发线程
* 负责监听下单成功信号,并启动线程池发通知
*/
public class MessageDispatcher extends Thread {
private final Stock stock;
private final ExecutorService pool;
public MessageDispatcher(Stock stock, ExecutorService pool) {
this.stock = stock;
this.pool = pool;
}
@Override
public void run() {
synchronized (stock) {
try {
while (!stock.ordered) {
System.out.println("消息线程:等待下单信号...");
stock.wait(); // 没下单就死等
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("消息线程:收到下单成功信号,开始并行发通知!");
// 2. 并行执行通知任务
pool.execute(() -> System.out.println("线程池任务:发送短信"));
pool.execute(() -> System.out.println("线程池任务:发放优惠券"));
pool.execute(() -> System.out.println("线程池任务:更新用户积分"));
}
}
}
```
## 2.4 主程序
```java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TraditionalDemo {
public static void main(String[] args) {
Stock stock = new Stock();
ExecutorService pool = Executors.newFixedThreadPool(3);
// 消息线程先启动(等待)
new MessageDispatcher(stock, pool).start();
// 模拟 3 个用户同时下单(竞争)
new OrderWorker(stock).start();
new OrderWorker(stock).start();
new OrderWorker(stock).start();
}
}
```
# 三、SpringBoot 异步方法
- @Transactional:保证库存扣减的事务性。
- @Async:将发短信、发券等耗时操作丢给线程池,立即释放 Tomcat 线程。
## 3.1 配置线程池
```java
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean("orderExecutor")
public Executor orderExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setThreadNamePrefix("Order-Async-");
executor.initialize();
return executor;
}
}
```
## 3.2 订单服务
```java
@Service
public class OrderService {
@Autowired
private StockService stockService;
@Autowired
private NotifyService notifyService;
/**
* 下单主流程
*/
public void createOrder() {
// 1. 扣库存(核心,同步)
boolean success = stockService.decreaseStock();
if (!success) {
throw new RuntimeException("库存不足");
}
// 2. 异步通知(非核心,并行)
notifyService.sendSms();
notifyService.sendCoupon();
}
}
```
## 3.3 通知服务
```java
@Service
public class NotifyService {
// 指定使用哪个线程池
@Async("orderExecutor")
public void sendSms() {
System.out.println(Thread.currentThread().getName() + " 发送短信");
}
@Async("orderExecutor")
public void sendCoupon() {
System.out.println(Thread.currentThread().getName() + " 发放优惠券");
}
}
```
# 四、SpringBoot 事件机制
- 事件Event下单成功这个“事实”。
- 发布者Publisher只负责发布事件不关心后续。
- 监听者Listener谁关心下单成功谁就干活且可以异步
## 4.1 定义事件
```java
public class OrderCreatedEvent {
private final String orderId;
public OrderCreatedEvent(String orderId) {
this.orderId = orderId;
}
public String getOrderId() {
return orderId;
}
}
```
## 4.2 发布事件
```java
@Service
public class OrderService {
@Autowired
private StockService stockService;
@Autowired
private ApplicationEventPublisher publisher;
public void createOrder() {
// 1. 扣库存
boolean success = stockService.decreaseStock();
if (success) {
// 2. 发布事件(我不关心谁处理)
publisher.publishEvent(new OrderCreatedEvent("ORDER_123"));
}
}
}
```
## 4.3 监听事件
```java
@Component
public class OrderListener {
// 监听下单事件,并异步执行
@EventListener
@Async("orderExecutor")
public void handleSendSms(OrderCreatedEvent event) {
System.out.println(Thread.currentThread().getName() + " 监听到事件,发送短信");
}
@EventListener
@Async("orderExecutor")
public void handleSendCoupon(OrderCreatedEvent event) {
System.out.println(Thread.currentThread().getName() + " 监听到事件,发放优惠券");
}
}
```