首页 > 编程语言 >[Java基础]虚拟线程

[Java基础]虚拟线程

时间:2024-08-24 20:53:09浏览次数:8  
标签:Java thread Thread CustomThread 虚拟 线程 public

虚拟线程(Virtual Thread)是 JDK 而不是 OS 实现的轻量级线程(Lightweight Process,LWP),由 JVM 调度。许多虚拟线程共享同一个操作系统线程,虚拟线程的数量可以远大于操作系统线程的数量。

虚拟线程和平台线程有什么关系?
在引入虚拟线程之前,java.lang.Thread 包已经支持所谓的平台线程(Platform Thread),也就是没有虚拟线程之前,我们一直使用的线程。JVM 调度程序通过平台线程(载体线程)来管理虚拟线程,一个平台线程可以在不同的时间执行不同的虚拟线程(多个虚拟线程挂载在一个平台线程上),当虚拟线程被阻塞或等待时,平台线程可以切换到执行另一个虚拟线程。

虚拟线程、平台线程和系统内核线程的关系图如下所示(图源:How to Use Java 19 Virtual Threads):

image

关于平台线程和系统内核线程的对应关系多提一点:在 Windows 和 Linux 等主流操作系统中,Java 线程采用的是一对一的线程模型,也就是一个平台线程对应一个系统内核线程。Solaris 系统是一个特例,HotSpot VM 在 Solaris 上支持多对多和一对一。具体可以参考 R 大的回答: JVM 中的线程模型是用户级的么?。

虚拟线程有什么优点和缺点?
优点
非常轻量级:可以在单个线程中创建成百上千个虚拟线程而不会导致过多的线程创建和上下文切换。
简化异步编程: 虚拟线程可以简化异步编程,使代码更易于理解和维护。它可以将异步代码编写得更像同步代码,避免了回调地狱(Callback Hell)。
减少资源开销: 由于虚拟线程是由 JVM 实现的,它能够更高效地利用底层资源,例如 CPU 和内存。虚拟线程的上下文切换比平台线程更轻量,因此能够更好地支持高并发场景。
缺点
不适用于计算密集型任务: 虚拟线程适用于 I/O 密集型任务,但不适用于计算密集型任务,因为密集型计算始终需要 CPU 资源作为支持。
与某些第三方库不兼容: 虽然虚拟线程设计时考虑了与现有代码的兼容性,但某些依赖平台线程特性的第三方库可能不完全兼容虚拟线程。
如何创建虚拟线程?
官方提供了以下四种方式创建虚拟线程:

使用 Thread.startVirtualThread() 创建
使用 Thread.ofVirtual() 创建
使用 ThreadFactory 创建
使用 Executors.newVirtualThreadPerTaskExecutor()创建
1、使用 Thread.startVirtualThread() 创建

public class VirtualThreadTest {
public static void main(String[] args) {
CustomThread customThread = new CustomThread();
Thread.startVirtualThread(customThread);
}
}

static class CustomThread implements Runnable {
@Override
public void run() {
System.out.println("CustomThread run");
}
}
2、使用 Thread.ofVirtual() 创建

public class VirtualThreadTest {
public static void main(String[] args) {
CustomThread customThread = new CustomThread();
// 创建不启动
Thread unStarted = Thread.ofVirtual().unstarted(customThread);
unStarted.start();
// 创建直接启动
Thread.ofVirtual().start(customThread);
}
}
static class CustomThread implements Runnable {
@Override
public void run() {
System.out.println("CustomThread run");
}
}
3、使用 ThreadFactory 创建

public class VirtualThreadTest {
public static void main(String[] args) {
CustomThread customThread = new CustomThread();
ThreadFactory factory = Thread.ofVirtual().factory();
Thread thread = factory.newThread(customThread);
thread.start();
}
}

static class CustomThread implements Runnable {
@Override
public void run() {
System.out.println("CustomThread run");
}
}
4、使用Executors.newVirtualThreadPerTaskExecutor()创建

public class VirtualThreadTest {
public static void main(String[] args) {
CustomThread customThread = new CustomThread();
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
executor.submit(customThread);
}
}
static class CustomThread implements Runnable {
@Override
public void run() {
System.out.println("CustomThread run");
}
}
虚拟线程和平台线程性能对比
通过多线程和虚拟线程的方式处理相同的任务,对比创建的系统线程数和处理耗时。

说明:统计创建的系统线程中部分为后台线程(比如 GC 线程),两种场景下都一样,所以并不影响对比。

测试代码:

public class VirtualThreadTest {
static List list = new ArrayList<>();
public static void main(String[] args) {
// 开启线程 统计平台线程数
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledExecutorService.scheduleAtFixedRate(() -> {
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
ThreadInfo[] threadInfo = threadBean.dumpAllThreads(false, false);
updateMaxThreadNum(threadInfo.length);
}, 10, 10, TimeUnit.MILLISECONDS);

    long start = System.currentTimeMillis();
    // 虚拟线程
    ExecutorService executor =  Executors.newVirtualThreadPerTaskExecutor();
    // 使用平台线程
    // ExecutorService executor =  Executors.newFixedThreadPool(200);
    for (int i = 0; i < 10000; i++) {
        executor.submit(() -> {
            try {
                // 线程睡眠 0.5 s,模拟业务处理
                TimeUnit.MILLISECONDS.sleep(500);
            } catch (InterruptedException ignored) {
            }
        });
    }
    executor.close();
    System.out.println("max:" + list.get(0) + " platform thread/os thread");
    System.out.printf("totalMillis:%dms\n", System.currentTimeMillis() - start);


}
// 更新创建的平台最大线程数
private static void updateMaxThreadNum(int num) {
    if (list.isEmpty()) {
        list.add(num);
    } else {
        Integer integer = list.get(0);
        if (num > integer) {
            list.add(0, num);
        }
    }
}

}
请求数 10000 单请求耗时 1s:

// Virtual Thread
max:22 platform thread/os thread
totalMillis:1806ms

// Platform Thread 线程数200
max:209 platform thread/os thread
totalMillis:50578ms

// Platform Thread 线程数500
max:509 platform thread/os thread
totalMillis:20254ms

// Platform Thread 线程数1000
max:1009 platform thread/os thread
totalMillis:10214ms

// Platform Thread 线程数2000
max:2009 platform thread/os thread
totalMillis:5358ms
请求数 10000 单请求耗时 0.5s:

// Virtual Thread
max:22 platform thread/os thread
totalMillis:1316ms

// Platform Thread 线程数200
max:209 platform thread/os thread
totalMillis:25619ms

// Platform Thread 线程数500
max:509 platform thread/os thread
totalMillis:10277ms

// Platform Thread 线程数1000
max:1009 platform thread/os thread
totalMillis:5197ms

// Platform Thread 线程数2000
max:2009 platform thread/os thread
totalMillis:2865ms
可以看到在密集 IO 的场景下,需要创建大量的平台线程异步处理才能达到虚拟线程的处理速度。
因此,在密集 IO 的场景,虚拟线程可以大幅提高线程的执行效率,减少线程资源的创建以及上下文切换。
注意:有段时间 JDK 一直致力于 Reactor 响应式编程来提高 Java 性能,但响应式编程难以理解、调试、使用,最终又回到了同步编程,最终虚拟线程诞生。

虚拟线程的底层原理是什么?

标签:Java,thread,Thread,CustomThread,虚拟,线程,public
From: https://www.cnblogs.com/DCFV/p/18378235

相关文章

  • 容器技术和虚拟机技术的对比
    目录容器和虚拟机的对比迁移性和性能隔离性资源限制解决的问题1.容器是如何进行隔离的?2.容器是如何进行资源限制的?3.简述下docker的文件系统?4.容器的启动过程?5.容器内运行多个应用的问题?容器和虚拟机的对比下面这张图是docker官方中截取下来的,我们来分析下docker和传统V......
  • 【C语言】进程和线程详解
    目录C语言进程和线程详解1.进程和线程的对比2.进程的基本概念2.1进程的定义2.2进程的特点2.3进程的生命周期3.进程管理3.1进程创建3.2进程间通信(IPC)3.2.1管道(Pipe)4.线程的基本概念4.1线程的定义4.2线程的特点5.POSIX线程库5.1引用头文件5.2创建线程......
  • Java学习第八周
    includeincludeincludeincludeincludeusingnamespacestd;time_tt=time(NULL);//设置当前时间staticintn=0;//总车次voidmenu();classbus//车票车次类{public:inthour;//发车时间(时)intminute;//发车时间(分)charstart_station[20];//起始站......
  • 基于java的校园二手物品交易平台(10902)
     有需要的同学,源代码和配套文档领取,加文章最下方的名片哦一、项目演示项目演示视频二、资料介绍完整源代码(前后端源代码+SQL脚本)配套文档(LW+PPT+开题报告)远程调试控屏包运行三、技术介绍Java语言SSM框架SpringBoot框架Vue框架JSP页面Mysql数据库IDEA/Eclipse开发四、项......
  • Java行为型设计模式-状态模式(含电梯场景示例)
    1.状态模式简介状态模式(StatePattern)是一种行为型设计模式,它允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。状态模式的目的是让状态转换显式,并且使得状态转换代码集中在一个地方,不需要使用多重条件语句。状态模式(StatePattern)用于解决系统中对......
  • 暑假学习Java第八周
    这个周Java学习了选择循环结构在Java编程语言中,选择结构和循环结构是两种基本的控制结构,用于指导程序的执行流程。选择结构选择结构让程序根据特定条件选择执行不同的代码路径1。if语句:基本形式: if(condition){statements;} if条件成立,则执行花括号内的语句;不成立,则跳......
  • 学生Java学习路程-8
    ok,到了一周一次的总结时刻,我大致会叙述这周学习了Java的那些东西。面向对象复习类和对象内存底层面向对象三大特征1.继承2.封装3.多态特殊类1.抽象类2.接口file类......
  • 基于Java Springboot校园跑腿系统
    一、作品包含源码+数据库+全套环境和工具资源+部署教程二、项目技术前端技术:Html、Css、Js、Vue、Element-ui数据库:MySQL后端技术:Java、SpringBoot、MyBatis三、运行环境开发工具:IDEA数据库:MySQL8.0数据库管理工具:Navicat10以上版本环境配置软件:JDK1.8+Maven3.6.3......
  • 基于Java Springboot海洋馆预约系统
    一、作品包含源码+数据库+设计文档万字+PPT+全套环境和工具资源+部署教程二、项目技术前端技术:Html、Css、Js、Vue、Element-ui数据库:MySQL后端技术:Java、SpringBoot、MyBatis三、运行环境开发工具:IDEA/eclipse数据库:MySQL5.7数据库管理工具:Navicat10以上版本环境......
  • 基于Java Springboot停车场车位预约系统
    一、作品包含源码+数据库+设计文档万字+PPT+全套环境和工具资源+部署教程二、项目技术前端技术:Html、Css、Js、Vue、Element-ui数据库:MySQL后端技术:Java、SpringBoot、MyBatis三、运行环境开发工具:IDEA/eclipse数据库:MySQL5.7数据库管理工具:Navicat10以上版本环境......