首页 > 其他分享 >虚拟线程常见问题总结

虚拟线程常见问题总结

时间:2024-11-12 20:47:57浏览次数:3  
标签:常见问题 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):

虚拟线程、平台线程和系统内核线程的关系

 

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

虚拟线程有什么优点和缺点?

优点

  • 非常轻量级:可以在单个线程中创建成百上千个虚拟线程而不会导致过多的线程创建和上下文切换。
  • 简化异步编程: 虚拟线程可以简化异步编程,使代码更易于理解和维护。它可以将异步代码编写得更像同步代码,避免了回调地狱(Callback Hell)。
  • 减少资源开销: 由于虚拟线程是由 JVM 实现的,它能够更高效地利用底层资源,例如 CPU 和内存。虚拟线程的上下文切换比平台线程更轻量,因此能够更好地支持高并发场景。

缺点

  • 不适用于计算密集型任务: 虚拟线程适用于 I/O 密集型任务,但不适用于计算密集型任务,因为密集型计算始终需要 CPU 资源作为支持。
  • 与某些第三方库不兼容: 虽然虚拟线程设计时考虑了与现有代码的兼容性,但某些依赖平台线程特性的第三方库可能不完全兼容虚拟线程。

如何创建虚拟线程?

官方提供了以下四种方式创建虚拟线程:

  1. 使用 Thread.startVirtualThread() 创建
  2. 使用 Thread.ofVirtual() 创建
  3. 使用 ThreadFactory 创建
  4. 使用 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 线程),两种场景下都一样,所以并不影响对比。

测试代码

请求数 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 性能,但响应式编程难以理解、调试、使用,最终又回到了同步编程,最终虚拟线程诞生。

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

如果你想要详细了解虚拟线程实现原理,推荐一篇文章:虚拟线程 - VirtualThread 源码透视

面试一般是不会问到这个问题的,仅供学有余力的同学进一步研究学习。

标签:常见问题,Thread,thread,CustomThread,虚拟,线程,public
From: https://blog.csdn.net/aaaa_1111111/article/details/143723225

相关文章

  • 虚拟定位之简单易操作
    **一.苹果手机端(无需越狱)工具:爱思助手:https://www.i4.cn/先拿数据线连接苹果手机,连接成功后修改后可以断开数据线连接,修改是否成功,可以去微信共享位置验证。二.电脑端工具:雷电模拟器:https://www.ldmnq.com可以改游戏的战区位置哦!......
  • Go语言并发编程:轻松驾驭多线程世界(九)
    Go语言并发编程:轻松驾驭多线程世界在这里插入图片描述在现代编程中,并发是让你的程序变得更强大、更高效的关键技能。幸运的是,Go语言提供了一种简单、直观的方式来处理并发任务,使用轻量级的Goroutine和Channel,让我们能够像指挥交通一样简单地处理多个任务。今天,我们将......
  • 运维系列&虚拟机系列:Ubuntu Server 24.04.1 配置静态ip
    UbuntuServer24.04.1配置静态ipUbuntuServer24.04.1配置静态ip1.找到NetPlan配置文件2.cat一下3.我这里用的无线网卡,修改wlp1s0下的配置4.保存文件后,执行5.检查IP地址和网络连接UbuntuServer24.04.1配置静态ip实体机安装完后,记录一下静......
  • 深入 Java 多线程:解锁并发编程的奥秘
    在当今的软件开发世界中,性能和高并发是衡量一个应用程序成败的关键因素。无论是处理高流量的网络请求、执行复杂的数据分析任务,还是管理后台服务中的资源,Java多线程编程都是开发者必备的技能之一。本文将带领你深入Java多线程的世界,解锁并发编程的奥秘。1.并发与并行的区......
  • 匿名内部类、Lambda表达式 应用于创建线程
    匿名内部类的几大作用:1.完成接口实现关系 / 完成类继承关系2.方法重写3.创建对象而Lambda表达式的作用:主要用于实现函数式接口,即用于实现单一抽象方法接口。所以可以用Lambda表达式实现的函数式接口都可以转换成匿名内部类的形式。方式一Threadt=newThread(){/......
  • node.js毕设虚拟财产交易系统(程序+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于虚拟财产交易系统的研究,现有研究主要集中在虚拟货币、虚拟物品等方面,专门针对虚拟财产交易系统整体设计与实现的研究较少。因此,本选题将以虚拟财产......
  • 创建线程池有哪几种方式
       Java中常见创建线程池的几种方法。1.使用​​Executors​​工具类创建线程池​​newFixedThreadPool(intnThreads)​​特点:创建一个固定大小的线程池,线程池中的线程数始终保持不变。适用场景:适用于任务量已知且相对固定的场景,可以有效控制资源的使用。​​ne......
  • 创建线程池有哪几种方式
      Java中常见创建线程池的几种方法。1.使用​​Executors​​工具类创建线程池​​newFixedThreadPool(intnThreads)​​特点:创建一个固定大小的线程池,线程池中的线程数始终保持不变。适用场景:适用于任务量已知且相对固定的场景,可以有效控制资源的使用。​​newSi......
  • Mit6.S081笔记Lab7: Multithreading 多线程
    课程地址:https://pdos.csail.mit.edu/6.S081/2020/schedule.htmlLab地址:https://pdos.csail.mit.edu/6.S081/2020/labs/thread.html我的代码地址:https://github.com/Amroning/MIT6.S081/tree/threadxv6手册:https://pdos.csail.mit.edu/6.S081/2020/xv6/book-riscv-rev1.pdf相......
  • CentOS虚拟机无法查看ipv4地址
    CentOS默认没有开启ens33vi/etc/sysconfig/network-scripts/ifcfg-ens33将最后一行的ONBOOT=no修改为ONBOOT=yes重启网卡服务systemctlrestartnetwork然后ipaddr查看ip目前这个是动态ip如果要静态ip继续编辑网卡配置文件ifcfg-ens33,将BOOTPROTO=dhcp修改为BOOT......