当前位置: 首页 > ai >正文

JDK21之虚拟线程

传统线程的三个痛点:

  • 重量级:每创建一个线程,操作系统都要分配栈内存、维护线程状态,成本高得很。

  • 切换成本高:线程一多,CPU得频繁在线程之间切换(上下文切换),性能开销大。

  • 受限于平台资源:比如 Linux 上默认线程栈大小是 1MB,意味着一个 8GB 内存的服务理论上最多跑 8000 个线程。

定义

虚拟线程是JVM层面实现的一种轻量级线程,不再直接依赖操作系统线程,而是由JVM自己调度和管理。

工作原理

虚拟线程通过将多个虚拟线程映射到少量的操作系统线程来工作。这种映射是动态的,JVM 可以在合适的时候将虚拟线程挂起或恢复,从而在物理线程之间共享资源。因此,虚拟线程的调度方式比传统的线程调度更加灵活和高效。

适用场景

虚拟线程适用于高并发的 I/O 密集型任务,例如:

  • I/O 密集型任务 :线程在等待 I/O(如网络请求、数据库查询)时自动挂起,载体线程可执行其他任务。
  • 高并发场景 :处理大量并发连接(如微服务、Web 服务器)。

虚拟线程适用于 I/O 密集型任务的原因

  • 用户态线程 :由 JVM 管理,不直接绑定内核线程,可创建数百万个虚拟线程。
  • 低资源消耗 :初始栈内存约 200B,挂起时自动释放载体线程(Carrier Thread)。

虚拟线程不适用于CPU密集型任务的原因

CPU密集型任务会持续暂用CPU,如果线程过多频繁线程切换会增加额外开销,导致整体吞吐量下降。

创建虚拟线程

方式 1:直接创建

// 创建并启动虚拟线程
Thread virtualThread = Thread.ofVirtual().start(() -> {System.out.println("Running in a virtual thread: " + Thread.currentThread());
});// 等待线程完成
virtualThread.join();

 方式 2:使用 Thread.Builder

Thread.Builder builder = Thread.ofVirtual().name("my-virtual-thread-", 0);
Thread vThread = builder.start(() -> {System.out.println("Thread name: " + Thread.currentThread().getName());
});

方式 3:通过线程池(推荐)

try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {for(int i = 0; i < 100; i++){// 提交任务(自动创建虚拟线程)executor.submit(() -> {System.out.println("Task running in virtual thread");});}} // 自动关闭线程池/**
* 虚拟线程在等待 I/O(如数据库、HTTP 请求)时自动挂起 ,释放底层平台线程,避免阻塞
*/
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {for (int i = 0; i < 10_000; i++) {executor.submit(() -> {// 模拟 I/O 操作(自动挂起虚拟线程)String response = httpClient.send(request, BodyHandlers.ofString());process(response);});}
}

 

传统线程池(平台线程)适用于 CPU 密集型任务的原因

  • 内核线程绑定 :每个平台线程对应一个操作系统线程(Kernel Thread),由 OS 调度。
  • 资源消耗高 :每个线程默认占用约 1MB 栈内存,大量线程导致内存压力和上下文切换开销。
  • 适用场景
    • CPU 密集型任务 :线程数通常设置为接近 CPU 核心数(Runtime.getRuntime().availableProcessors()),最大化利用 CPU 资源。
    • 同步阻塞操作 :若线程在 I/O 或锁等待时阻塞,会导致线程资源浪费。
传统线程池的优化策略
  • 固定线程数 :通过 Executors.newFixedThreadPool(nThreads) 限制线程数,避免过多线程导致资源耗尽。
  • 任务队列缓冲 :使用有界/无界队列(如 LinkedBlockingQueue)暂存任务,但队列过长可能引发高延迟或 OOM。

能否用虚拟线程替代传统线程池?

1. 可替代的场景
  • 纯异步 I/O 任务 :如 HTTP 服务、数据库访问、消息队列消费等,虚拟线程显著提升吞吐量。
  • 高并发低延迟需求 :虚拟线程通过减少线程切换和内存开销,更适合处理大量短暂任务。
2. 不可替代或需谨慎的场景
  • CPU 密集型任务
    虚拟线程的载体线程数有限(默认等于 CPU 核心数),若虚拟线程执行 CPU 密集型操作,会阻塞载体线程,导致整体吞吐量下降。

  • 同步代码块或 Native 方法

    • 若虚拟线程进入 synchronized 块或调用 JNI 方法,会固定绑定到载体线程,丧失调度灵活性。
    • 需改用 ReentrantLock 并配合 tryLock() 实现非阻塞同步。
  • 依赖 ThreadLocal 的代码
    虚拟线程支持 ThreadLocal,但大量使用可能导致内存泄漏(因虚拟线程生命周期短且数量多)。建议改用 Scoped Values(JDK 20+)。

http://www.xdnf.cn/news/5031.html

相关文章:

  • 在Mathematica中加速绘制图形(LibraryLink)
  • Vue3项目中如何实现网页加载进度条。
  • 专题练习1
  • 图像移动图像归类代码
  • 仁合医疗进博会:创新成果闪耀亮相
  • [逆向工程]什么说ASLR技术(二十三)
  • 操作系统导论——第26章 并发:介绍
  • 剖析 Java 23 特性:深入探究最新功能
  • Android framework功能配置开发
  • SQL JOIN 关联条件和 where 条件的异同
  • AnyTXTSearcher电脑本地文件搜索工具
  • 深入理解 Vue 全局导航守卫:分类、作用与参数详解
  • AVL树:保持平衡的高效二叉搜索树
  • apipost快捷使用实例
  • 43.防雷击浪涌设计
  • 计算机系统结构-第九章-互联网络 第十章
  • Windows系统下【Celery任务队列】python使用celery 详解(一)
  • AIOps 工具介绍
  • Python程序打包为EXE文件的全面指南
  • 面试常考算法2(核心+acm模式)
  • [AI ][Dify] Dify Tool 插件调试流程详解
  • 使用 Python 构建图像编辑应用:一步步指南
  • 强化学习PPO算法学习记录
  • 并发设计模式实战系列(19):监视器(Monitor)
  • 支付宝沙盒模式商家转账经常出现 响应异常: 解包错误
  • 《微机原理》微机程序段 计算机编程数据分区
  • 修改docker为国内源
  • YOLOv12云端GPU谷歌免费版训练模型
  • 访问网页的全过程(分步骤的详细解析)
  • 【java反射修改注解属性】java 通过反射,动态修改注解的某个属性值