什么是虚拟线程?与普通线程的区别

news2025/4/18 5:05:45
引言:线程的演进与挑战

在传统的并发编程中,线程是一种非常重要的概念。我们使用线程来实现任务的并发执行,从而提高程序的执行效率。普通线程(如 Thread 类)是一种重量级的线程,每个线程都对应着操作系统内核中的一个线程,这意味着系统需要为每个线程分配独立的资源(如栈空间、内存等),从而可能导致性能瓶颈,尤其是在需要大量并发线程时。

为了克服这个问题,Java 在 JDK 21 中引入了 虚拟线程(Virtual Threads)。虚拟线程是轻量级的线程,它们由 Java 的 JVM 管理,并不直接依赖操作系统的线程调度机制,因此能够大规模地创建和管理大量并发任务。

在这篇文章中,我们将深入探讨虚拟线程的概念,并与传统的普通线程进行对比,帮助你理解虚拟线程的优势以及在实际开发中的应用场景。


一、普通线程的特点

普通线程(也称为操作系统线程)是操作系统直接管理的线程。每个线程都有自己的堆栈、程序计数器等资源。操作系统通过 线程调度器 来调度和管理这些线程,确保它们在多个处理器核心上执行。

普通线程的特点:
  • 操作系统管理:每个普通线程都由操作系统内核直接管理。
  • 重量级:创建和销毁线程的成本较高,因为操作系统需要为每个线程分配堆栈和其他资源。
  • 并发受限:由于线程创建开销大,操作系统通常会限制同时运行的线程数量,导致高并发时出现资源竞争和上下文切换的开销。
  • 上下文切换:操作系统通过上下文切换来切换不同线程的执行状态,这个过程是有成本的,特别是在大量线程的情况下。

二、虚拟线程的概念

虚拟线程是 JDK 21 引入的一项新特性,它为 Java 提供了一种轻量级的并发模型。虚拟线程并不依赖操作系统的线程调度,而是由 JVM 负责调度和管理。每个虚拟线程的栈大小和执行成本都比普通线程小得多,因此可以大规模地创建虚拟线程,从而实现高并发。

虚拟线程的特点:
  • JVM管理:虚拟线程由 JVM 管理,而非操作系统。JVM 会将多个虚拟线程映射到少量的操作系统线程上。
  • 轻量级:虚拟线程的栈空间小,创建和销毁的成本也远低于操作系统线程。
  • 大规模并发:可以创建成千上万甚至更多的虚拟线程,而不会导致性能瓶颈。
  • 调度效率高:由于 JVM 管理线程调度,虚拟线程的上下文切换非常高效,几乎不需要操作系统的参与。
  • 适合 IO 密集型任务:虚拟线程特别适合处理大量的 IO 密集型任务,因为它们的生命周期成本低,能够快速切换。

三、虚拟线程和普通线程的区别

虚拟线程和普通线程有很多显著的区别,以下是几个关键点:

特性普通线程虚拟线程
管理者操作系统(内核线程)JVM(用户空间线程)
创建成本较高,需要为每个线程分配栈和资源较低,创建虚拟线程的成本非常小
栈空间每个线程都有独立的栈空间,通常为1MB左右轻量级的栈空间,通常为几KB到几十KB
线程调度操作系统负责调度JVM负责调度,依赖于 JVM 的线程池
上下文切换操作系统进行上下文切换,较慢JVM 高效的上下文切换,几乎无成本
适用场景适用于 CPU 密集型任务适用于 IO 密集型任务
线程数限制受操作系统限制,通常在几十到几百个之间可以创建成千上万的虚拟线程
性能开销线程创建和销毁成本较高,内存占用大线程创建和销毁成本低,内存占用少

四、虚拟线程的优势

  1. 大规模并发处理:

    • 由于虚拟线程的栈空间较小,且创建和销毁成本低,理论上可以创建数百万个虚拟线程。这使得它在处理高并发任务时,比传统的线程更具优势。
    • 例如,处理大量独立的 IO 操作(如 HTTP 请求处理、数据库查询等)时,虚拟线程能够提供极高的性能。
  2. 低内存占用:

    • 虚拟线程的内存开销比普通线程要小得多。每个虚拟线程的栈大小仅为普通线程的几分之一,因此可以在有限的内存空间中创建更多的线程。
  3. 高效的上下文切换:

    • 传统线程的上下文切换由操作系统负责,通常较为昂贵。而虚拟线程的上下文切换是由 JVM 管理的,效率极高,几乎没有开销。
  4. 适应异步编程模型:

    • 虚拟线程非常适合处理异步任务和 IO 密集型操作,能够以同步的方式编写异步代码。例如,在处理大量 HTTP 请求时,可以通过虚拟线程编写出更简洁、易于理解的同步代码,而不需要传统的回调或 Future。

五、如何使用虚拟线程

JDK 21 引入了一个名为 java.util.concurrent.VirtualThread 的新 API,它使得虚拟线程的使用变得非常简单。下面是如何在 Java 中使用虚拟线程的一个基本示例:

public class VirtualThreadExample {

    public static void main(String[] args) {
        // 创建一个虚拟线程并启动
        Thread virtualThread = Thread.ofVirtual().start(() -> {
            System.out.println("Hello from virtual thread!");
        });

        // 等待虚拟线程执行完成
        virtualThread.join();
    }
}

在上面的代码中,我们使用 Thread.ofVirtual() 来创建虚拟线程,虚拟线程启动后会执行指定的任务。与传统线程相比,虚拟线程的使用方式几乎没有变化。


六、虚拟线程的应用场景

虚拟线程非常适合以下场景:

  • 高并发的 IO 密集型任务:例如 Web 服务器、网络爬虫、文件系统操作等。虚拟线程能够处理大量的并发请求,而不需要过多的内存开销。
  • 异步编程模型:通过虚拟线程,可以用同步的方式处理异步任务,使得代码更加简洁易懂。
  • 任务调度系统:虚拟线程也非常适合用于任务调度系统,可以大规模地调度并发任务。

七、总结:虚拟线程的未来

虚拟线程的引入为 Java 并发编程提供了全新的选择,使得我们能够更加高效地处理大规模并发任务。它的轻量级、高效性和低内存占用,使得虚拟线程成为处理 IO 密集型任务的理想选择。

在未来,随着 Java 生态的进一步发展,我们预计虚拟线程会在更多的领域得到应用,特别是在大规模并发处理和高性能计算领域。

如果你目前还在使用传统的线程池来处理并发任务,虚拟线程无疑是一个值得尝试的技术,它可以大大简化你的代码并提升性能。

推荐阅读文章

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 什么是 Cookie?简单介绍与使用方法

  • 什么是 Session?如何应用?

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • 如何理解应用 Java 多线程与并发编程?

  • 把握Java泛型的艺术:协变、逆变与不可变性一网打尽

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 如何理解线程安全这个概念?

  • 理解 Java 桥接方法

  • Spring 整合嵌入式 Tomcat 容器

  • Tomcat 如何加载 SpringMVC 组件

  • “在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”

  • “避免序列化灾难:掌握实现 Serializable 的真相!(二)”

  • 如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)

  • 解密 Redis:如何通过 IO 多路复用征服高并发挑战!

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • “打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”

  • Java 中消除 If-else 技巧总结

  • 线程池的核心参数配置(仅供参考)

  • 【人工智能】聊聊Transformer,深度学习的一股清流(13)

  • Java 枚举的几个常用技巧,你可以试着用用

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • 探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)

  • 为什么用了 @Builder 反而报错?深入理解 Lombok 的“暗坑”与解决方案(二)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2332491.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

edis 主从复制

Redis 主从复制是一种数据同步机制,主节点(Master)将数据复制到一个或多个从节点(Slave),从 而实现数据备份、读写分离和高可用性。 1、解决我们的日常一个单机故障,而衍生出来 主从架构 2、…

机器视觉+深度学习,让电子零部件表面缺陷检测效率大幅提升

在精密加工的3C电子行业中,一抹0.1毫米的油渍,一粒肉眼难辨的灰尘或将引发整机性能隐患。当制造业迈入微米级品质竞争时代,产品表面看似微不足道的脏污缺陷,正成为制约企业高质量发展的隐形枷锁。分布无规律的污渍斑点、形态各异的…

Java基础关键_035_Lambda 表达式

目 录 一、引例:TreeSet 排序 1.实现 Comparable 接口 2.比较器 3.匿名内部类 4.Lambda 表达式 5.Lambda 表达式和匿名内部类的区别 二、函数式编程 三、Lambda 表达式的使用 1.无返回值函数式接口 (1)无返回值无参数 (…

OPEX baota 2024.02.26

OPEX baota 2024.02.26 运维集成软件宝塔2024.02.26作废例子: 最重要的两个地方:上传文件 网站,重启应用服务器(tomcat) 其他很少用的

若依 前后端部署

后端:直接把代码从gitee上拉去到本地目录 (https://gitee.com/y_project/RuoYi-Vue ) 注意下redis连接时password改auth 后端启动成功 前端:运行前首先确保安装了node环境,随后执行: !!一定要用管理员权限…

LeetCode算法题(Go语言实现)_37

题目 给你一棵以 root 为根的二叉树,二叉树中的交错路径定义如下: 选择二叉树中 任意 节点和一个方向(左或者右)。 如果前进方向为右,那么移动到当前节点的的右子节点,否则移动到它的左子节点。 改变前进方…

使用 react-three-fiber 快速重构 Three.js 场景⚛️

不明白的知识先放在一边,激发兴趣是第一步,所以不必纠结代码的细节,相信我你很快就会爱上这种感觉!!! 今天,我们将更进一步,将上一篇中vite npm传统 Three.js 原生代码完整 重构为 …

RT-Thread 屏蔽在线软件包的方法

说明 可能大家对 RT-Thread 的 Kconfig 配置项,Scons 构建有些疑惑,其实 BSP 的 Kconfig 可以自由的配置,目录也可以自由的调整 RT-Thread BSP 默认都有在线软件包的配置项,如果你不需要在线软件包,也可以把这个配置项…

深入理解Java反射

反射(Reflection)是Java语言的一个强大特性,它允许程序在运行时动态地获取类的信息并操作类或对象的属性、方法和构造器。就是在获取运行时的java字节码文件,通过各种方法去创建对象,反射是Java被视为动态语言的关键特性之一。 反射其实就是…

Apipost自定义函数深度实战:灵活处理参数值秘籍

在开发过程中,为了更好地处理传递给接口的参数值,解决在调试过程中的数据处理问题,我们经常需要用到函数处理数据。 过去,我们通过预执行脚本来处理数据,先添加脚本,然后将处理后的结果再赋值给请求参数。…

对重大保险风险测试的算法理解

今天与同事聊到重大保险风险测试,借助下面链接的文章, 谈IFRS 17下的重大保险风险测试 - 知乎 谈一下对下图这个公式的理解。 尤其是当看到下面这段文字的解释时,感觉有些算法上的东西,需要再澄清一些。 首先,上面文…

如何白嫖Grok3 API? 如何使用Grok3 API调用实例?怎么使用Grok3模型?

前段时间,Grok3(想要体验Grok3的童鞋可以参考本文:Grok 上线角色扮演功能,教你课后作业手到擒来,Grok3使用次数限制?如何使用Grok3? Grok3国内支付手段如何订阅升级Premium - AI is all your need!&#x…

Fast网络速度测试工具

目录 网站简介 功能特点 测试过程 为什么使用Fast 如果网络速度不达标 网站简介 Fast是一个由Netflix提供的网络速度测试工具,主要用来测试用户的互联网下载速度。它以其简洁的界面和快速的测试过程而受到用户的欢迎。 功能特点 下载速度测试:这是…

ubuntu20.04在mid360部署direct_lidar_odometry(DLO)

editor:1034Robotics-yy time:2025.4.10 1.下载DLO,mid360需要的一些...: 1.1 在工作空间/src下 下载DLO: git clone https://github.com/vectr-ucla/direct_lidar_odometry 1.2 在工作空间/src下 下载livox_ros_driver2&…

制造企业数据治理体系搭建与业务赋能实践

当下制造企业正面临着前所未有的机遇与挑战,从多环节业务协同的复杂性,到海量数据资源的沉睡与孤岛化;从个性化定制需求的爆发,到供应链效率优化的迫切性——如何通过数据治理将“数据包袱”转化为“数据资产”,已成为…

【LunarVim】解决which-key 自定义键位注册不成功问题

问题描述 LunarVim将which-key设置放在一个keymaps.lua中,然后config.lua调用reload “user.keymaps”,键位没用注册成功,而直接写在config.lua中,就注册成功 这暴露了LunarVim 插件和配置加载顺序的一些细节坑,下面解…

开源推荐#5:CloudFlare-ImgBed — 基于 CloudFlare Pages 的开源免费文件托管解决方案

大家好,我是 jonssonyan。 寻找一个稳定、快速、还最好是免费或成本极低的图床服务,一直是许多开发者、博主和内容创作者的痛点。公共图床可能说关就关,付费服务又增加成本。现在,一个名为 CloudFlare-ImgBed 的开源项目&#xf…

算法训练之动态规划(三)

♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…

xv6-labs-2024 lab2

lab-2 0. 前置 课程记录 操作系统的隔离性,举例说明就是,当我们的shell,或者qq挂掉了,我们不希望因为他,去影响其他的进程,所以在不同的应用程序之间,需要有隔离性,并且&#xff0…

基于FPGA实现BPSK 调制

目录 一、 任务介绍二、基本原理三、基于FPGA实现BPSK 调制四、源码 一、 任务介绍 BPSK 调制在数字通信系统中是一种极重要的调制方式,它的抗干扰噪声性能及通频带的利用率均优先于 ASK 移幅键控和 FSK 移频键控。因此,PSK 技术在中、高速数据传输中得…