diff --git a/docs/.vitepress/theme/router/index.ts b/docs/.vitepress/theme/router/index.ts index 6a99aa5..d2fbc6e 100644 --- a/docs/.vitepress/theme/router/index.ts +++ b/docs/.vitepress/theme/router/index.ts @@ -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' } ] }, { diff --git a/docs/Web/SpringBoot/SpringAOP.md b/docs/Web/SpringBoot/Spring-AOP.md similarity index 100% rename from docs/Web/SpringBoot/SpringAOP.md rename to docs/Web/SpringBoot/Spring-AOP.md diff --git a/docs/Web/SpringBoot/SpringIOC.md b/docs/Web/SpringBoot/Spring-IOC.md similarity index 100% rename from docs/Web/SpringBoot/SpringIOC.md rename to docs/Web/SpringBoot/Spring-IOC.md diff --git a/docs/Web/SpringBoot/SpringMVC.md b/docs/Web/SpringBoot/Spring-MVC.md similarity index 100% rename from docs/Web/SpringBoot/SpringMVC.md rename to docs/Web/SpringBoot/Spring-MVC.md diff --git a/docs/Web/SpringBoot/SpringBootBean.md b/docs/Web/SpringBoot/SpringBoot-Bean.md similarity index 100% rename from docs/Web/SpringBoot/SpringBootBean.md rename to docs/Web/SpringBoot/SpringBoot-Bean.md diff --git a/docs/Web/SpringBoot/SpringBootStarter.md b/docs/Web/SpringBoot/SpringBoot-Starter.md similarity index 100% rename from docs/Web/SpringBoot/SpringBootStarter.md rename to docs/Web/SpringBoot/SpringBoot-Starter.md diff --git a/docs/Web/SpringBoot/SpringBoot-Thread.md b/docs/Web/SpringBoot/SpringBoot-Thread.md new file mode 100644 index 0000000..145a475 --- /dev/null +++ b/docs/Web/SpringBoot/SpringBoot-Thread.md @@ -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() +); +``` + +  **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()); + } +} +``` + +# 二、案例 +  案例:电商秒杀系统。 +- 资源竞争:多个用户抢同一件商品(多线程抢锁)。 +- 异步解耦:扣减库存后,需要发短信、发优惠券(多线程并行)。 +- 系统解耦:订单系统不应依赖短信系统(事件驱动)。 + +# 二、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() + " 监听到事件,发放优惠券"); + } +} +``` \ No newline at end of file