【Java】多线程详解

【Java 多线程详解(2026 最新版)】
从入门到生产级实战,涵盖传统平台线程 + 虚拟线程(Project Loom) + 结构化并发

2026 年 3 月,Java 26 已进入 Release Candidate(3 月 17 日正式 GA),Java 25 是最新 LTS。虚拟线程 已彻底稳定(自 Java 21),成为高并发应用的标配;结构化并发 在 Java 26 中进入第六次预览,几乎可以生产使用。


1. 为什么需要多线程?传统 vs 现代

维度传统平台线程(Platform Thread)虚拟线程(Virtual Thread,Java 21+)
创建成本高(对应 1 个 OS 线程)极低(几 KB 内存,可创建百万级)
阻塞行为阻塞整个 OS 线程只阻塞虚拟线程,载体线程可复用
适用场景CPU 密集型I/O 密集型(HTTP、DB、文件、网络)
线程池必要性必须严格控制通常不需要线程池,直接 new Thread
代码风格复杂(Executor + Future)接近同步代码风格

核心结论:2026 年写新代码,I/O 场景默认用虚拟线程;CPU 密集型仍用平台线程 + ForkJoinPool。


2. 线程基础(必知)

创建线程的三种方式(2026 仍有效)

// 1. 继承 Thread(不推荐)
class MyThread extends Thread {
    public void run() { System.out.println("线程运行"); }
}

// 2. 实现 Runnable(推荐,Java 8 前主流)
Runnable task = () -> System.out.println("Lambda 方式");

// 3. 实现 Callable + Future(有返回值)
Callable<Integer> callable = () -> {
    Thread.sleep(1000);
    return 42;
};

2026 推荐创建方式(虚拟线程):

// 方式1:最简单
Thread vt = Thread.ofVirtual().name("my-vt").unstarted(() -> {
    System.out.println("我是虚拟线程,当前载体线程:" + Thread.currentThread());
});
vt.start();
vt.join();

// 方式2:用 Thread.startVirtualThread(快捷方式)
Thread.startVirtualThread(() -> { /* 任务 */ });

线程状态(6 种,虚拟线程映射相同)

NEW → RUNNABLE → BLOCKED/WAITING/TIMED_WAITING → TERMINATED


3. 同步与可见性

synchronized(重量级锁,2026 仍常用)

synchronized (obj) { /* 临界区 */ }

// 方法锁
public synchronized void method() { }

volatile(仅保证可见性,不保证原子性)

private volatile boolean flag = true;

Lock 接口(推荐 ReentrantLock)

ReentrantLock lock = new ReentrantLock();
lock.lock();
try { /* 临界区 */ } finally { lock.unlock(); }

ReadWriteLockStampedLock(乐观读,性能更高)。


4. 线程池(ExecutorService)

2026 年仍然是 CPU 密集型标配。

ExecutorService pool = Executors.newFixedThreadPool(10);     // 固定大小
ExecutorService cached = Executors.newCachedThreadPool();    // 自动伸缩(I/O 场景已不推荐)
ExecutorService workStealing = Executors.newWorkStealingPool(); // ForkJoin 底层

// 推荐自定义 ThreadPoolExecutor(可监控)
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue,
    threadFactory, handler);

虚拟线程下:通常不需要线程池,可直接用 Executors.newVirtualThreadPerTaskExecutor()(Java 21+)。


5. java.util.concurrent 核心工具(JUC)

工具类用途典型场景
ConcurrentHashMap并发 HashMap缓存、统计
CopyOnWriteArrayList读多写少 List事件监听器
BlockingQueue生产者-消费者Array/Linked/Synchronous
CountDownLatch倒计时门闩多线程初始化完成
CyclicBarrier可重用栅栏多线程分阶段计算
Semaphore信号量(限流)数据库连接池
Phaser多阶段栅栏复杂分阶段任务
Exchanger线程间交换数据生产者-消费者缓冲

CompletableFuture(Java 8+,异步神器)

CompletableFuture.supplyAsync(() -> "hello")
    .thenApply(String::toUpperCase)
    .thenCombine(otherFuture, (a, b) -> a + b)
    .exceptionally(ex -> "error")
    .join();

6. 原子类(AtomicXXX)

AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet();        // CAS 操作,无锁

支持 LongAdder(高并发下性能更好)、LongAccumulator。


7. Fork/Join 框架(CPU 密集型王者)

class SumTask extends RecursiveTask<Long> { ... }
ForkJoinPool pool = ForkJoinPool.commonPool();
Long result = pool.invoke(new SumTask(1, 1_000_000));

8. 虚拟线程(Project Loom)—— 2026 重头戏 ★★★★★

核心概念

  • 虚拟线程由 JVM 管理,不是 OS 线程。
  • 多个虚拟线程可挂载到同一个载体线程(Carrier Thread,即平台线程)。
  • 遇到阻塞(sleep、IO、synchronized、park)时,虚拟线程会卸载(unmount),载体线程去执行其他虚拟线程。

创建方式(2026 推荐)

// 1. 快捷方式
Thread.startVirtualThread(() -> {
    // 这里可以写同步风格代码
    try (var client = HttpClient.newHttpClient()) {
        var resp = client.send(...);
    }
});

// 2. 自定义
Thread.ofVirtual()
    .name("user-vt-")
    .uncaughtExceptionHandler((t, e) -> log.error(...))
    .start(runnable);

// 3. 使用 Executor(推荐大规模任务)
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    for (int i = 0; i < 1_000_000; i++) {
        executor.submit(() -> handleRequest());
    }
} // 自动 shutdown

适用场景(2026 共识)

  • Web 服务(Spring Boot 6 / Tomcat / Undertow 已原生支持)
  • 微服务调用、数据库连接池、文件读写、消息队列消费
  • 不适合:纯 CPU 计算(仍用平台线程)

注意事项 & 陷阱(Pinning 问题)

虚拟线程遇到以下情况会被“钉住”(pinned)在载体线程上,导致无法卸载:

  • synchronized 块/方法(Java 25+ 已大幅优化)
  • JNI 本地方法
  • 类初始化等待(Java 26 已修复)

最佳实践

  • 尽量用 ReentrantLock / Concurrent 集合代替 synchronized
  • 数据库连接池用 HikariCP + virtual threads 专用配置

9. 结构化并发(Structured Concurrency,Java 21+ 预览)

Java 26 中为 第六次预览(JEP 525),即将正式。

try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
    Future<String> user  = scope.fork(() -> fetchUser());
    Future<Order>  order = scope.fork(() -> fetchOrder());

    scope.join();           // 等待所有完成
    scope.throwIfFailed();  // 任意失败则抛异常

    return new Response(user.resultNow(), order.resultNow());
}

优点:自动取消、结构化错误处理、清晰作用域。


10. 2026 年多线程最佳实践(生产必看)

  1. 默认使用虚拟线程处理 I/O。
  2. CPU 密集型Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()) 或 ForkJoin。
  3. 永远不要手动 new Thread() + start()(除非极特殊场景)。
  4. 必须关闭 ExecutorService(try-with-resources 或 shutdown)。
  5. 共享状态 优先用 Concurrent 集合 + Atomic
  6. 监控:用 jstackVisualVMJFR(Java Flight Recorder)观察虚拟线程状态。
  7. 避免死锁:统一加锁顺序,或用 tryLock()
  8. 日志与异常:虚拟线程中未捕获异常会调用 Thread.setDefaultUncaughtExceptionHandler

总结:2026 年 Java 多线程心法

  • 写代码:像写单线程一样写(虚拟线程 + 结构化并发)。
  • 性能:百万并发不再是梦。
  • 维护性:代码更清晰,bug 更少。
  • 迁移:老项目逐步把 I/O 线程池换成 newVirtualThreadPerTaskExecutor()

想继续深入某个模块?

  • Spring Boot 3.3+ 虚拟线程完整配置
  • 虚拟线程 + Reactor/WebFlux 实战
  • 结构化并发完整示例
  • 线程池参数调优公式
  • JFR 监控虚拟线程

直接告诉我,我立刻给你对应完整代码 + 配置!🚀

文章已创建 4845

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部