JDK17-21特性Virtual-Threads详解
Virtual Threads 详解一、知识概述Virtual Threads(虚拟线程)是 Java 21 引入的重大特性,它是 Project Loom 项目的核心成果。虚拟线程是一种轻量级的线程实现,由 JVM 而非操作系统管理,可以极大地提高并发程序的可扩展性。1.1 传统线程的局限性在虚拟线程出现之前,Java 的线程是与操作系统线程一一对应的:Java Thread (Platform Thread) ←→ OS Thread这种映射方式存在以下问题:资源消耗大:每个 OS 线程占用约 1MB 栈空间创建成本高:创建线程需要系统调用数量受限:一台服务器通常只能创建几千个线程上下文切换开销:OS 级别的线程切换成本高1.2 虚拟线程的解决方案虚拟线程采用 M:N 的调度模型:多个 Virtual Thread (M) ←→ 少量 Carrier Thread (N) ←→ OS Thread (N)优势:轻量级:每个虚拟线程只占用几百字节数量不限:可以创建数百万个虚拟线程高效调度:JVM 级别的调度,切换成本低简化编程:使用传统同步编程模型实现高并发二、知识点详细讲解2.1 虚拟线程基础2.1.1 创建虚拟线程importjava.util.concurrent.Executors;importjava.util.concurrent.ThreadFactory;publicclassVirtualThreadCreation{publicstaticvoidmain(String[]args)throwsException{// 方式1:使用 Thread.startVirtualThread()ThreadvThread1=Thread.startVirtualThread(()-{System.out.println("Hello from virtual thread: "+Thread.currentThread());});vThread1.join();// 方式2:使用 Thread.BuilderThreadvThread2=Thread.ofVirtual().name("my-virtual-thread").unstarted(()-System.out.println("Using Thread.Builder"));vThread2.start();vThread2.join();// 方式3:使用 Executors.newVirtualThreadPerTaskExecutor()try(varexecutor=Executors.newVirtualThreadPerTaskExecutor()){executor.submit(()-System.out.println("From executor"));}// 方式4:使用 ThreadFactoryThreadFactoryfactory=Thread.ofVirtual().factory();ThreadvThread3=factory.newThread(()-{System.out.println("Created by factory");});vThread3.start();vThread3.join();// 判断是否为虚拟线程System.out.println("Is virtual: "+Thread.currentThread().isVirtual());}}2.1.2 虚拟线程与平台线程对比publicclassThreadComparison{publicstaticvoidmain(String[]args){// 平台线程ThreadplatformThread=Thread.ofPlatform().name("platform-thread").unstarted(()-{System.out.println("Platform thread: "+Thread.currentThread());System.out.println("Is virtual: "+Thread.currentThread().isVirtual());});// 虚拟线程ThreadvirtualThread=Thread.ofVirtual().name("virtual-thread").unstarted(()-{System.out.println("Virtual thread: "+Thread.currentThread());System.out.println("Is virtual: "+Thread.currentThread().isVirtual());});platformThread.start();virtualThread.start();// 查看线程属性System.out.println("\n平台线程属性:");System.out.println(" 栈大小: "+platformThread.getStackTrace().length);System.out.println("\n虚拟线程属性:");System.out.println(" 是否虚拟: "+virtualThread.isVirtual());}}2.2 虚拟线程调度2.2.1 调度原理importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;publicclassVirtualThreadScheduling{publicstaticvoidmain(String[]args)throwsException{// 查看载波线程(Carrier Thread)System.out.println("Available processors: "+Runtime.getRuntime().availableProcessors());// 创建多个虚拟线程,观察调度try(ExecutorServiceexecutor=Executors.newVirtualThreadPerTaskExecutor()){for(inti=0;i10;i++){inttaskId=i;executor.submit(()-{StringthreadName=Thread.currentThread().getName();System.out.println("Task "+taskId+" running on: "+threadName);// 模拟阻塞操作try{Thread.sleep(100);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}System.out.println("Task "+taskId+" completed");});}}}}2.2.2 固定载波线程数importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.ThreadFactory;publicclassCustomCarrierThreads{publicstaticvoidmain(String[]args){// 默认情况下,载波线程数等于 CPU 核心数// 可以通过系统属性调整System.setProperty("jdk.virtualThreadScheduler.parallelism","4");System.setProperty("jdk.virtualThreadScheduler.maxPoolSize","8");try(ExecutorServiceexecutor=Executors.newVirtualThreadPerTaskExecutor()){for(inti=0;i20;i++){intid=i;executor.submit(()-{System.out.println("Task "+id+": "+Thread.currentThread());try{Thread.sleep(1000);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}});}}}}2.3 阻塞操作与挂载/卸载2.3.1 阻塞操作的自动挂载importjava.io.IOException;importjava.net.ServerSocket;importjava.net.Socket;importjava.util.concurrent.Executors;publicclassBlockingOperationsDemo{publicstaticvoidmain(String[]args)throwsException{// 启动一个简单的服务器try(ServerSocketserverSocket=newServerSocket(8080);varexecutor=Executors.newVirtualThreadPerTaskExecutor())