IWA
2025-11-19
点 赞
0
热 度
4
评 论
0

Java Virtual Threads(虚拟线程)教程:从零入门(第 1 篇)

系列主题:Java Virtual Threads(虚拟线程)教程:从零上手到实战优化


一、为什么要学习 Virtual Threads?(为什么它成为热点)

Java 在 JDK 19 引入 Virtual Threads(预览)后,到 JDK 21 成为正式特性,是 Java 最大的变革之一。
它的目标非常简单:

让 Java 的并发变得更轻,更简单,更快,让每个并发任务都能拥有自己的线程。

传统 Java 并发难点:

问题

描述

线程太“重”

每个 OS Thread 占用 ~1MB 堆外内存,无法开太多

I/O 密集型程序困难

RPC、DB、HTTP 请求会阻塞线程

复杂的线程池设计

业务量不稳定时,线程池经常成为瓶颈

高并发=高复杂度

Reactor 风格(CompletableFuture、WebFlux)可读性差

而虚拟线程的出现,让 Java 拥有了协程级别的能力:

Virtual Thread 的优势

  1. 线程超轻量:几十 KB,百万级线程不是问题

  2. 阻塞等同于异步 I/O:写同步风格就能跑出异步性能

  3. 基本不需要线程池调优

  4. 代码可读性极佳,能回归传统同步写法

  5. JDK 官方维护,性能、稳定性、生态直接受益

一句话总结:虚拟线程让 Java 写法变简单,性能变更强。


二、Virtual Thread 到底是什么?(核心概念)

Java 传统线程是绑定在 OS 级线程上的:

Java Thread = 内核线程

虚拟线程则是:

Virtual Thread = 由 JVM 管理的“用户态线程”

从模型上来看:

           ┌──────────────────────────┐
           │  虚拟线程(几万~百万)    │
           └──────────────────────────┘
                      ↓ 调度
           ┌──────────────────────────┐
           │   少量平台线程(几十个) │
           └──────────────────────────┘
                      ↓
           ┌──────────────────────────┐
           │         CPU 核心         │
           └──────────────────────────┘

虚拟线程不是线程池,它是百万级并发的“线程模型革命”。


三、快速体验:创建你的第一个虚拟线程

虚拟线程使用方式非常简单。

方式1:Thread.ofVirtual().start()

public class HelloVirtualThread {
    public static void main(String[] args) {
        Thread thread = Thread.ofVirtual().start(() -> {
            System.out.println("Hello from Virtual Thread!");
        });
    }
}

方式2:使用 Executors(JDK21 推荐)

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    executor.submit(() -> {
        System.out.println("Running in Virtual Thread");
    });
}

每个任务一个虚拟线程,不再需要复杂的线程池调优。


四、虚拟线程的核心行为:阻塞≠慢

传统线程中,阻塞调用是性能杀手:

Thread.sleep(2000); // 真的占用线程 2 秒

在虚拟线程中:

Thread.sleep(2000); // 虚拟线程挂起,不占用平台线程

虚拟线程的阻塞是“廉价”的,因为阻塞时:

  • 虚拟线程会 自动让出平台线程

  • 不占用 CPU 或 OS Thread 资源

这意味着你可以回到同步代码写法,而获得异步的性能。


五、对比:10000 个线程的创建成本

传统线程(Platform Thread)版本

public class PlatformThreadTest {
    public static void main(String[] args) {
        for (int i = 0; i < 10000; i++) {
            new Thread(() -> {
                try { Thread.sleep(1000); } catch (Exception ignored) {}
            }).start();
        }
    }
}

结果:
非常慢
❌ 可能 OOM
❌ 占用大量内存


虚拟线程版本

public class VirtualThreadTest {
    public static void main(String[] args) {
        for (int i = 0; i < 10000; i++) {
            Thread.ofVirtual().start(() -> {
                try { Thread.sleep(1000); } catch (Exception ignored) {}
            });
        }
    }
}

结果:
几毫秒创建完毕
内存占用很低
轻松扩展到 100 万线程


六、虚拟线程适用的场景(非常重要)

场景

是否适合

原因

I/O 密集型业务(DB 查询、HTTP 调用、RPC)

✔ 完美适配

阻塞时自动让出平台线程

高并发服务端应用

每个请求一个虚拟线程即可

爬虫、批处理任务

需要创建大量小任务

CPU 密集型计算

❌ 不适合

仍然受 CPU 核心数限制

虚拟线程并不能提高 CPU 性能,但可以极大提高 I/O 密集型系统吞吐量。


七、注意事项:什么时候不要使用虚拟线程?

1. CPU 密集型计算

虚拟线程不会让 CPU magically 变强。

2. 阻塞式同步集合(如 ReentrantLock)过多

虽然能用,但会降低性能。
推荐使用 无锁结构、CASConcurrent 系列集合。

3. 自定义线程池(大多数情况不需要)

如业务复杂但线程池配置反而成为累赘。


八、总结:第 1 篇你应该学会了什么?

通过本篇,你应该已经明确:

✔ Virtual Threads 的出现是因为传统线程过重

✔ 它是一种“用户态线程”,由 JVM 管理,非常轻量

✔ 适用于 I/O 密集型业务,能创建百万线程

✔ 使用方式极其简单:Thread.ofVirtual() 或 Executors

✔ 阻塞是廉价的,可像写同步代码一样获得异步性能

✔ 下一篇将正式进入实战:HTTP、数据库、RPC 的虚拟线程优化


下一篇预告(第 2 篇)

《使用 Virtual Threads 重构传统同步代码:HTTP/DB/RPC 实战提升》

内容将包含:

  • 使用虚拟线程优化 HTTP 客户端(同步写法性能媲美异步)

  • 优化数据库查询的并发吞吐

  • 重构传统线程池代码

  • 对虚拟线程调度的深入讲解



用键盘敲击出的不只是字符,更是一段段生活的剪影、一个个心底的梦想。希望我的文字能像一束光,在您阅读的瞬间,照亮某个角落,带来一丝温暖与共鸣。

IWA

estp 企业家

具有版权性

请您在转载、复制时注明本文 作者、链接及内容来源信息。 若涉及转载第三方内容,还需一同注明。

具有时效性

文章目录

IWA的艺术编程,为您导航全站动态

32 文章数
9 分类数
10 评论数
32标签数
最近评论
IWA

IWA


👍

M丶Rock

M丶Rock


😂

M丶Rock

M丶Rock


感慨了

M丶Rock

M丶Rock


厉害了

M丶Rock

M丶Rock


6666666666666666666