并发基础
threads、virtual-threads、volatile。
35 分钟
并发基础
Web 与批处理常需 同时做多件事。java-fundamentals 未展开线程——本课补 Thread、虚拟线程、volatile 与 synchronized 入门,并对照 jva-concurrency 的线程池进阶。
学习目标
- 创建并启动线程,理解 Runnable 与 Thread
- 使用 JDK 21 虚拟线程处理高并发阻塞 IO
- 知道 volatile 与 synchronized 的可见性/互斥作用
线程基础
Runnable task = () -> System.out.println(Thread.currentThread().getName());
Thread t = new Thread(task, "worker-1");
t.start();
t.join(); // 等待结束
| 概念 | 说明 |
|---|---|
| 进程 | JVM 实例,资源隔离 |
| 线程 | 进程内执行单元,共享堆 |
| 栈 | 每线程独立栈帧 |
不要 无节制 new Thread();生产环境用线程池(见 jva-concurrency)。
虚拟线程(JDK 21)
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i ->
executor.submit(() -> fetchLesson("jvc-" + i))
);
}
- 虚拟线程 轻量,阻塞 IO 时挂起不占用 OS 线程
- 适合 高并发、阻塞多 的任务(HTTP 客户端、JDBC)
- CPU 密集计算仍用平台线程 + 有限池
volatile 与 synchronized
public class Counter {
private volatile boolean shutdown = false;
private int count = 0;
public synchronized void increment() {
count++;
}
public void shutdown() {
shutdown = true; // volatile 保证其他线程可见
}
}
- volatile:保证读写可见性,不保证复合操作原子性
- synchronized:互斥 + 可见性;锁方法或锁块
- 计数器优先
AtomicInteger(进阶课展开)
共享可变状态是并发 bug 温床;能隔离就不用锁(每请求新建对象、不可变 record)。
练习
- 用两个平台线程并行打印 slug 列表
- 用虚拟线程 executor 提交 100 个 sleep 任务并计时
- 解释为何 在多线程下可能丢更新