【Java】虚拟线程与Java 8普通线程池的对比

embedded/2024/10/18 8:28:54/

文章目录

      • IO密集型任务
      • 高并发Web服务器
      • 异步编程
      • 微服务架构
      • 大规模并行处理
      • 事件驱动的应用
      • 不适用的场景
      • 使用对比
      • 性能分析
        • 资源消耗
        • 并发能力
        • 性能测试
      • 总结

在JDK 21之前,Java并发编程主要依赖于传统的线程池,如Java 8中的 Executors.newFixedThreadPool()

虚拟线程(Virtual Threads)是JDK 21引入的一种新型线程,它们旨在解决传统线程在轻量级并发任务处理中的局限性。以下是虚拟线程适用的场景:

IO密集型任务

虚拟线程特别适用于IO密集型任务,因为这些任务通常会花费大量时间等待外部资源,如网络响应、文件读写等。在等待期间,虚拟线程可以被挂起,而不占用操作系统线程资源,从而允许更多的虚拟线程在同一时间内运行。

高并发Web服务器

在Web服务器中,通常需要处理大量的并发请求,这些请求往往是IO密集型的。使用虚拟线程可以显著提高服务器的并发处理能力,因为它们能够以极低的成本创建数百万个线程。

异步编程

虚拟线程与Project Loom中的结构化并发(Structured Concurrency)相结合,为异步编程提供了更好的支持。这使得编写和维护异步代码更加容易。

微服务架构

在微服务架构中,服务之间通常会有大量的网络调用。虚拟线程可以用来处理这些网络调用,提高服务的响应速度和吞吐量。

大规模并行处理

当需要并行处理大量任务时,如大数据处理、分布式计算等,虚拟线程可以提供更高的并行度,因为它们不受物理线程数量的限制。

事件驱动的应用

事件驱动的应用,如消息队列消费者、事件流处理等,可以利用虚拟线程来处理大量的事件,而不需要为每个事件分配一个操作系统线程。

不适用的场景

虽然虚拟线程在许多场景下都非常有用,但以下场景可能不太适合使用虚拟线程

  • CPU密集型任务虚拟线程并不提供比传统线程更好的CPU利用率。对于CPU密集型任务,操作系统线程可能更合适,因为它们可以直接映射到CPU核心。
  • 需要精确线程控制的场景:如果应用程序需要精细控制线程的调度和行为,使用传统线程可能更为合适。
    总之,虚拟线程适用于那些需要大量并发、高吞吐量、且任务执行时间主要花费在等待外部资源响应的场景。在实际应用中,开发者应根据具体的应用需求和资源特性来决定是否使用虚拟线程

使用对比

Java 8普通线程池

在Java 8中,创建一个固定大小的线程池并执行任务通常如下:

java">import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
public class ThreadPoolExample {public static void main(String[] args) {// 创建一个固定大小的线程池ExecutorService executor = Executors.newFixedThreadPool(10);// 使用IntStream并发处理10000个任务IntStream.range(0, 10000).forEach(i -> {executor.submit(() -> {System.out.println("处理任务:" + i);// 模拟任务执行时间try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}});});// 关闭线程池executor.shutdown();}
}

在这个例子中,我们创建了一个固定大小为10的线程池。这意味着即使我们有10000个任务,同一时间也只有10个任务在执行。

虚拟线程

而使用虚拟线程的示例已经在之前的段落中给出。虚拟线程可以创建数百万个,而不受物理线程数量的限制。

性能分析

资源消耗
  • 普通线程池:每个线程都对应一个操作系统线程,创建和销毁线程的成本较高,且占用较多的内存和处理器资源。
  • 虚拟线程虚拟线程是轻量级的,它们共享同一个或几个操作系统线程,因此创建和销毁的成本非常低,且占用的资源远少于普通线程。
并发能力
  • 普通线程池:由于操作系统线程资源的限制,线程池的大小通常受限,这限制了应用程序的并发能力。
  • 虚拟线程:由于虚拟线程的资源消耗非常低,可以创建大量的虚拟线程,从而实现更高的并发能力。
性能测试

以下是一个简单的性能测试,比较在处理大量任务时,普通线程池和虚拟线程的性能差异。

java">import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
public class PerformanceTest {public static void main(String[] args) throws InterruptedException {// 普通线程池性能测试long startTimePool = System.nanoTime();ExecutorService poolExecutor = Executors.newFixedThreadPool(100);IntStream.range(0, 1000000).forEach(i -> poolExecutor.submit(() -> {// 模拟任务执行}));poolExecutor.shutdown();poolExecutor.awaitTermination(1, TimeUnit.HOURS);long endTimePool = System.nanoTime();// 虚拟线程性能测试long startTimeVirtual = System.nanoTime();ExecutorService virtualExecutor = Executors.newVirtualThreadPerTaskExecutor();IntStream.range(0, 1000000).forEach(i -> virtualExecutor.submit(() -> {// 模拟任务执行}));virtualExecutor.shutdown();virtualExecutor.awaitTermination(1, TimeUnit.HOURS);long endTimeVirtual = System.nanoTime();// 输出结果System.out.println("普通线程池执行时间: " + TimeUnit.NANOSECONDS.toMillis(endTimePool - startTimePool) + " ms");System.out.println("虚拟线程执行时间: " + TimeUnit.NANOSECONDS.toMillis(endTimeVirtual - startTimeVirtual) + " ms");}
}

在这个测试中,我们分别用普通线程池和虚拟线程执行了100万个任务。虚拟线程通常会比普通线程池更快完成这些任务,因为它们创建和切换的成本更低。

总结

虚拟线程在处理大量并发任务时,相比Java 8普通线程池具有明显的性能优势。它们更加轻量级,可以创建更多数量的线程,从而提高应用程序的并发处理能力。然而,虚拟线程也并非万能,它们适用于IO密集型任务,而在CPU密集型任务中,传统线程可能仍然具有优势。在实际开发中,应根据具体场景选择合适的并发模型。


http://www.ppmy.cn/embedded/120531.html

相关文章

C++ STL(1)迭代器

文章目录 一、迭代器详解1、迭代器的定义与功能2、迭代器类型3、示例4、迭代器失效4.1、vector 迭代器失效分析4.2、list 迭代器失效分析4.3、set 与 map 迭代器失效分析 5、总结 前言: 在C标准模板库(STL)中,迭代器是一个核心概念…

XHTML学习

XHTML学习 1.XHTML 简介2.XHTML - 元素标准3.XHTML - 属性标准 1.XHTML 简介 XHTML是一个严格遵循 XML语法规则的 HTML 标准。它是 HTML4 的一种重构版本,结合了 HTML 的灵活性和 XML 的严格性,如今XHTML已经得到了所有主流浏览器的支持 与 HTML 相比最…

Metasploit渗透测试之服务端漏洞利用

简介 在之前的文章中,我们学习了目标的IP地址,端口,服务,操作系统等信息的收集。信息收集过程中最大的收获是服务器或系统的操作系统信息。这些信息对后续的渗透目标机器非常有用,因为我们可以快速查找系统上运行的服…

基于STM32的智能家居交互终端:使用FreeRTOS与MQTT协议的流程设计

一、项目概述 简要介绍项目的目标和用途 随着智能家居的普及,家庭智能交互终端成为提升居住体验的重要设备。本文将介绍一个基于STM32的家庭智能交互终端的设计与实现,该终端能够通过触摸屏、语音识别和传感器数据采集等功能,提供家庭环境监…

OpenHarmony(鸿蒙南向)——平台驱动指南【PWM】

往期知识点记录: 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~ 持续更新中…… 概述 功能简介 PWM即脉冲宽度调制(Pulse Width Modul…

基于SpringBoot+Vue的留学信息推荐系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…

centos72009源码编译R语言

./dev/make-distribution.sh --name custom-spark --pip --r --tgz -Pconnect -Psparkr -Phive -Phive-thriftserver -Pmesos -Pyarn -Dhadoop.version3.4.0 -Pkubernetes spark3.5.3 源码版本 ./dev/make-distribution.sh --name custom-spark --pip --r --tgz -Pconnect -P…

JAVA笔记 | 实际上用到的策略模式(可直接套用)

自己开发中用到了策略模式,这样写不一定是最好的,但是满足了业务场景跟使用要求,做个笔记,下次有用到可以快速复习跟套用 假设使用场景:有几只宠物,猫跟狗等,要求他们做各种动作,比如…