news 2026/4/16 5:39:31

JDK 21 中的虚拟线程:革新 Java 多线程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JDK 21 中的虚拟线程:革新 Java 多线程

JDK 21 中引入的虚拟线程是 Java 并发生态系统的一个重要里程碑。本文将介绍虚拟线程的基础知识和最佳实践。

什么是虚拟线程?

多线程是业界广泛用于开发基于 Java 的应用程序的特性。它允许我们并行运行操作,从而加快任务执行速度。任何 Java 应用程序创建的线程数量都受限于操作系统能够处理的并行操作数量 ;换句话说,Java 应用程序中的线程数量等于操作系统线程的数量。考虑到当前快速发展的生态系统,这一限制一直是应用程序进一步扩展的瓶颈。

为了克服这一限制,Java 在 JDK 21 中引入了虚拟线程的概念。Java 应用程序创建一个虚拟线程,该线程不与任何操作系统线程关联。这意味着每个虚拟线程都不需要依赖于平台线程(即操作系统线程)。虚拟线程可以独立处理任何任务,并且仅在需要执行 I/O 操作时才会获取平台线程

这种获取和释放平台线程的机制使应用程序能够灵活地创建尽可能多的虚拟线程,从而实现高并发性。

1,JDK 21 之前的线程

在 JDK 21 之前,所有java.lang.Thread 类的实例都是操作系统线程,也称为平台线程。

这意味着在 JDK 环境中创建的每个线程都必须映射到一个平台线程。这种机制限制了 JVM 环境中可创建的线程数量。由于创建平台线程的成本很高,过去通常会使用线程池来避免重复创建线程,但这会增加应用程序的性能开销。

2,JDK 21 之后的线程

在 JDK 21 中,应用程序开发人员可以选择使用Thread.ofVirtual() API 或 Executors.newVirtualThreadPerTaskExecutor() 创建虚拟线程,而不是平台线程。

以这种方式创建的线程在 JVM 内部运行,不会占用任何操作系统线程。虚拟线程可以像平台线程一样执行所有并发任务。虚拟线程需要平台线程来执行 I/O 操作,I/O 操作完成后,虚拟线程会释放平台线程。虚拟线程不需要线程池管理。由于它们是 JVM 内部的,因此系统中可以拥有无​​限数量的虚拟线程。

为什么需要虚拟线程?

  • 高吞吐量:包含大量并发操作的任务(例如服务器应用程序)会花费大量时间等待。Web 服务器通常需要处理大量客户端请求。如果没有虚拟线程,它们处理并行请求的能力将受到限制。使用虚拟线程可以处理大量并发请求,从而提升服务器的处理能力。
  • 无需线程池:虚拟线程资源占用低,可用性高,因此无需使用线程池。对于每个并发任务,我们都可以创建一个虚拟线程,这就像在 JVM 内存中创建一个对象一样简单。
  • 高性能:创建虚拟线程耗时更少(因为无需操作系统级别的操作),因此可以提升应用程序的整体性能。
  • 更低的内存消耗:每个虚拟线程都在堆中维护一个栈,用于存储局部变量和方法调用。每个虚拟线程可以创建多个子线程,并且这些子线程的生命周期很短,因此每个线程的调用栈都很浅,内存消耗极低。
  • 可扩展解决方案:API密集型应用程序通常采用每个请求一个线程的设计方式。由于虚拟线程允许JVM创建比平台线程更多的线程,因此应用程序可以扩展以服务大量客户端请求。

如何创建虚拟线程

当前的 JDK 框架支持两种创建虚拟线程的方法。以下是创建虚拟线程的示例代码。

方法一:使用 接口

Thread.Builder builder = Thread.ofVirtual().name("NewThread"); Runnable task = () -> { System.out.println("Running thread"); }; Thread t = builder.start(task); System.out.println("Thread name: " + t.getName());

方法二: 框架

try (ExecutorService myExecutor = Executors.newVirtualThreadPerTaskExecutor()) { Future<?> future = myExecutor.submit(() -> System.out.println("Running a new thread")); future.get(); System.out.println("Task completed");

性能对比:虚拟线程 vs 平台线程

我创建了一个简单的程序来展示虚拟线程和平台线程之间的性能差异。

代码片段

//Store 类用于存储由奇数和偶数生成的线程数。它使用并发哈希映射来存储这些数据。 public class Store { private ConcurrentHashMap<Integer, Integer> concurrentHashMap = new ConcurrentHashMap<Integer, Integer>(); public synchronized void addQuantity(int productId){ int key = productId % 2; concurrentHashMap.computeIfAbsent(key,k->0); concurrentHashMap.computeIfPresent(key,(k,v)->v+1); } public Map<Integer, Integer> getStoreData(){ return concurrentHashMap; } }
//这个类充当一个任务,由多个线程执行。每个线程都有一个任务,即递增存储中的计数。 public class ComputationTask implements Runnable{ int productId; Store store; public ComputationTask(Store store, int id){ this.store = store; productId=id; } @Override public void run() { store.addQuantity(productId); }
//这个主类包含实例化虚拟线程和平台线程的逻辑。它会创建超过 1000 个线程,所有线程完成工作后,代码会打印哈希映射条目以及整个进程所花费的总时间。 public class Main { public static void main(String[] args) throws InterruptedException { long pid = ProcessHandle.current().pid(); System.out.println("Process ID: " + pid); Thread.Builder builder = null; Store store = new Store(); builder = Thread.ofVirtual().name("virtual worker-", 0); // builder = Thread.ofPlatform().name("platform worker-", 0); long starttime = System.currentTimeMillis(); for (int i = 1; i < 1000; i++) { ComputationTask task = new ComputationTask(store, i); Thread t1 = builder.start(task); t1.join(); System.out.println(t1.getName() + " started"); } Map<Integer,Integer> map = store.getStoreData(); map.entrySet().stream() .forEach(entry -> System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue())); long endtime = System.currentTimeMillis(); System.out.println("Total Computation Time - "+(endtime-starttime)+" miliseconds"); } }

执行结果

使用虚拟线程执行程序:

virtual worker-0 started virtual worker-1 started virtual worker-2 started virtual worker-3 started …………………………………. …………………………………. virtual worker-995 started virtual worker-996 started virtual worker-997 started virtual worker-998 started virtual worker-999 started Key: 0, Value: 500 Key: 1, Value: 500 Total Computation Time - 147 miliseconds Process finished with exit code 0

使用平台线程执行程序。

注释掉虚拟线程,在 Main.java 中创建代码,然后取消注释创建平台线程的代码。

platform worker-0 started platform worker-1 started platform worker-2 started platform worker-3 started …………………………………….. …………………………………….. platform worker-995 started platform worker-996 started platform worker-997 started platform worker-998 started platform worker-999 started Key: 0, Value: 500 Key: 1, Value: 500 Total Computation Time - 551 miliseconds Process finished with exit code 0

根据上述结果可知,当程序创建 1000 个虚拟线程并执行特定操作时,耗时 147 毫秒;而相同的代码如果使用平台线程运行,则大约需要 551 毫秒才能完成。因此,虚拟线程比平台线程具有更好的性能。

使用虚拟线程的最佳实践

  • 虚拟线程仅在执行同步代码块时才会绑定到平台线程。因此,应避免频繁且持续时间长的同步代码块,以缩短平台线程的生命周期,从而充分利用虚拟线程模型。
  • 切勿创建虚拟线程池,因为虚拟线程数量庞大,创建新的虚拟线程开销很小。如果没有线程池,JVM 就不需要处理复杂的逻辑来维护线程池和进行调度。
  • 避免使用异步代码编写技术,因为在同步代码中,服务器会为每个传入的请求分配一个线程,并持续处理整个请求周期。由于虚拟线程数量众多,阻塞它们的开销很小,因此值得鼓励。
  • 虚拟线程支持线程局部变量。但是,由于虚拟线程数量可能很多,因此应谨慎使用线程局部变量。不要使用线程局部变量来在线程池中共享同一线程的多个任务之间分配昂贵的资源。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 13:01:23

YOLO如何对接RTSP视频流?GPU解码性能优化

YOLO如何对接RTSP视频流&#xff1f;GPU解码性能优化 在智能安防、工业质检和交通监控等实际场景中&#xff0c;我们常常需要对来自网络摄像头的实时视频流进行目标检测。一个典型的诉求是&#xff1a;如何让YOLO模型稳定、低延迟地处理多路RTSP高清视频流&#xff1f; 这个问题…

作者头像 李华
网站建设 2026/4/16 12:42:45

生成式AI搜索的跨行业革命与商业模式重构

引言&#xff1a;当每个行业都面临搜索重构 生成式AI搜索不是单一行业的变革&#xff0c;而是正在重塑从医疗健康到金融服务、从教育到法律、从零售到制造业的每一个知识密集型领域。这种变革不是渐进式的改进&#xff0c;而是根本性的价值转移和商业模式重构。本文将深入分析…

作者头像 李华
网站建设 2026/4/15 23:19:30

YOLO目标检测支持多语言标签?GPU加速文本渲染

YOLO目标检测支持多语言标签&#xff1f;GPU加速文本渲染 在一条自动化质检产线上&#xff0c;摄像头每秒捕捉数百帧图像&#xff0c;AI系统需要实时识别出“表面划痕”“螺丝缺失”等缺陷&#xff0c;并将结果以中文标签叠加显示在监控大屏上。如果标签延迟半秒、字体模糊甚至…

作者头像 李华
网站建设 2026/4/16 10:37:03

YOLO模型剪枝后,推理速度提升50%?实测结果来了

YOLO模型剪枝后&#xff0c;推理速度提升50%&#xff1f;实测结果来了 在工业质检产线、智能零售货架或无人机巡检任务中&#xff0c;一个共同的挑战浮出水面&#xff1a;如何让高精度的目标检测模型在算力有限的边缘设备上跑得又快又稳&#xff1f;YOLO系列作为实时检测的“顶…

作者头像 李华
网站建设 2026/4/16 13:04:59

开源YOLO镜像上线!一键部署目标检测,附免费token领取

开源YOLO镜像上线&#xff01;一键部署目标检测&#xff0c;附免费token领取 在智能安防、工业质检、自动驾驶等场景中&#xff0c;实时准确地“看见”并识别目标&#xff0c;是构建智能化系统的第一步。然而对大多数开发者而言&#xff0c;从零搭建一个稳定高效的目标检测服务…

作者头像 李华