打破并发瓶颈:虚拟线程实现详解与传统线程模型的性能对比
目录
一、定义与特性
二、虚拟线程实现
2.1 使用 Thread.startVirtualThread() 创建
2.2 使用 Thread.ofVirtual() 创建
2.3 使用 ThreadFactory 创建
2.4 使用 Executors.newVirtualThreadPerTaskExecutor()创建
三、虚拟线程和普通线程的区别
3.1 线程管理方式不同
3.2 创建成本不同
3.3 并发编程模型的简化
3.4 阻塞操作的影响
一、定义与特性
定义:
(1)虚拟线程是
Java19
提出来的一个概念,Java19
提供特性预览,开放实装是Java21。
(2)虚拟线程是一种由JVM而非操作系统直接管理的线程。它独立于操作系统。虚拟线程是依附于主线程的,如果主线程销毁了,虚拟线程也不复存在。
特性(优点):
1.轻量级:虚拟线程的创建和销毁代价极低,与传统线程相比内存占用少。
2.高并发:支持数百万级别的并发进程,不会因线程数量限制系统性能。
3.与传统线程兼容:完全兼容现有的线程API,无需修改代码即可引入虚拟线程。
缺点:
1.不适用于计算密集型任务:虚拟线程适用于I/O密集型任务,但不适用于计算密集型任务,因为密集型计算始终需要CPU资源作为支持。
2.与某些第三方库不兼容。
二、虚拟线程实现
虚拟线程的使用和普通线程几乎一样,唯一的区别在于创建虚拟线程只能通过特定的方法。
在SpringBoot中使用虚拟线程要求SpringBoot的版本最低是
3.x
,JDK的版本不能低于21
2.1 使用 Thread.startVirtualThread()
创建
直接通过Thread静态方法创建,该方式无法指定线程名称,线程名称默认为:null
@Testvoid testVirtualThread4() {Thread.startVirtualThread(() -> System.out.printf("线程ID:%s - 任务执行完成", Thread.currentThread().threadId())) ;}
2.2 使用 Thread.ofVirtual()
创建
ofVirtual()方法创建的
虚拟线程默认是自动执行的,可创建不自动启动的线程,手动执行。
@Testvoid testVirtualThread2() {// 创建虚拟线程并自动执行Thread.Builder.OfVirtual virtual = Thread.ofVirtual().name("pack1");virtual.start(() -> System.out.printf("%s - VirtualThread1自动执行任务完成\n", Thread.currentThread().getName()));// 创建不自动启动的线程Thread thread = virtual.unstarted(() -> System.out.printf("%s - VirtualThread1手动执行任务完成\n", Thread.currentThread().getName()));// 手动启动虚拟线程thread.start();}
2.3 使用 ThreadFactory
创建
@Testvoid testVirtualThread3() {ThreadFactory threadFactory = Thread.ofVirtual().name("threadFactory").factory();threadFactory.newThread(() -> System.out.printf("%s - 通过工厂创建执行任务完成", Thread.currentThread().getName())).start();}
2.4 使用 Executors.newVirtualThreadPerTaskExecutor()
创建
创建一个执行器,为每个任务启动一个新的虚拟线程
@Testvoid testVirtualThread1() {try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {IntStream.range(0, 10_000).forEach(i -> executor.submit(() -> {Thread.sleep(Duration.ofSeconds(1));System.out.println(STR."task: \{i}");return i;}));}}
三、虚拟线程和普通线程的区别
3.1 线程管理方式不同
- 虚拟线程:虚拟线程由JVM管理,少量映射到操作系统线程上,实现轻量化,避免了直接依赖操作系统的线程创建、调度和销毁开销。
- 普通线程:传统的线程是由操作系统直接管理的,每创建一个线程都会占用系统资源,并由操作系统负责调度。
3.2 创建成本不同
- 虚拟线程:创建成本低,因为不需要操作系统的参与,大多数管理工作由JVM来完成。
- 普通线程:创建成本比较高,每个线程都会占用一部分操作系统的资源,如:内存和CPU,并且需要频繁的上下文切换。
3.3 并发编程模型的简化
- 虚拟线程:虚拟线程轻量高效,无需复杂线程池管理,每个任务可直接分配独立线程执行。
- 普通线程:传统线程开销大,通常需线程池优化,避免频繁创建销毁。
3.4 阻塞操作的影响
- 虚拟线程:虚拟线程能高效处理阻塞操作,JVM可轻量挂起阻塞线程并调度其他任务,几乎无系统压力。
- 普通线程:阻塞操作会导致线程挂起,高并发时可能耗尽系统资源。