虚拟线程探索与实践

优质博文:IT-BLOG-CN

一、简介

虚拟线程是轻量级线程,极大地减少了编写、维护和观察高吞吐量并发应用的工作量。虚拟线程是由JEP 425提出的预览功能,并在JDK 19中发布,JDK 21中最终确定虚拟线程,以下是根据开发者反馈从JDK 20中的变化:
【1】jdk21中虚拟线程始终支持线程本地变量。与在预览版本中允许的不同,现在不再可能创建不能具有线程本地变量的虚拟线程。对线程本地变量的有保障支持确保了许多现有库可以不经修改地与虚拟线程一起使用,并有助于将以任务为导向的代码迁移到使用虚拟线程。
【2】直接使用Thread.Builder API创建的虚拟线程(而不是通过Executors.newVirtualThreadPerTaskExecutor()创建的虚拟线程)现在默认情况下也会在其生命周期内进行监控,并且可以通过描述在"观察虚拟线程"部分中的新线程转储来观察。

基于协程的线程,与其他语言中的协程有相似之处,也有不同。虚拟线程是依附于主线程的,如果主线程销毁了,虚拟线程也不复存在。

二、背景

1、大量应用时同步方式,修改成异步方式投入资源大;
2、由线程池被打满引起的事故很难杜绝,很多应用将核心和非核心的应用一起交由线程池管理;

解决上面问题有两种措施:
1、NIO:优点是有成熟框架ReactorRxJava等。缺点是可读性欠缺,改造难度大;
2、虚拟线程:优点是业务侧改造成本低,无需池化,天然隔离。缺点是对nativesynchronize方法或者外部函数不友好;

三、原理

调度方式: 当前线程将任务提交给虚拟线程的时候,是一个Runnalbe状态,存放在队列中排队。任务排到第一位后,会挂在到平台线程上Platform Thread,该线程就是用户线程New Thread的线程。当任务挂载上去之后,就是一个运载线程,执行虚拟线程中的任务。当线程执行到阻塞或者IO操作的时候,它会将当前任务卸载到队列中,重新编程Runnable状态。

状态机: 与平台的线程的状态相似,我们主要看下如下两个状态的变化

RUNNING -> PARKING与普通线程一致,通常由各种block导致触发后置为PARKING状态,卸载虚拟线程,调用Continuation.yield()方法
RUNNING -> YIELDING通常为IO阻塞时置为YIELDING状态,卸载虚拟线程,调用Thread.yield

四、使用场景

计算密集型

CPU机密型: 并行开启X个任务,每个任务对5W个随机数进行排序;

结论:虚拟线程对于CPU密集型应用无优势

IO密集型

并发数CPU响应时间(ms)吞吐量
103519490
205520925
3080221296
4095261468
5099321508

结论:虚拟线程在CPU使用率达到80以后,性能有些许衰退。

结论: 相同的并发下
1、由于虚拟线程不需要大量的系统线程调度,节省了CPU的开销;
2、系统线程的大量减少,减少了CPU_Load排队的情况;
3、虚拟线程替换了dal的线程池,减少了线程数量(上面包含了JVM自身的线程和框架的线程);

使用案例代码:

CDubboClient instance = CDubboClient.getInstance();
FlightPassengerWS service = instance.getService(FlightPassengerWS.class);
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {StudentResponseType studentResponse = executor.submit( () -> service.getStudent(request).get());
}

五、死锁

synchronize同步代码块导致的死锁现象:

结论: 虚拟线程获取了连接后IO发生了卸载,当链接数耗尽,装载状态的虚拟线程由于拿不到链接被BLOCK,发生yield。由于在同步代码块中,yield失败发生绑定。导致其他获取链接的虚拟线程无运载线程可用。

解决办法: 使用ReentrantLock替换Synchronized

private final ReentranLock synLock = new ReentranLock();
synchronized(this) {}
// 替换为
synLock.lock();
try {} finally {synLock.unlock();
}

六、实践

QPS 1000+ 的项目性能监控

平台线程虚拟线程
CPU使用率(avg)20%15%
CPU_Load(max)155.5
线程数(avg)260258
时间响应(avg)118ms97ms
P99.93460ms1676ms

使用虚拟线程后,由于切换了线程,无法从HttpContext.current()获取到任何信息,需要在虚拟线程里threadlocal重新set

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/414912.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

k8s---ingress对外服务(traefik)

目录 ingress的证书访问 traefik traefik的部署方式: deamonset deployment nginx-ingress与traefix-ingress相比较 nginx-ingress-controller ui访问 deployment部署 ingress的证书访问 ingress实现https代理访问: 需要证书和密钥 创建证书 密钥 secre…

【SpringBoot3】IDEA常用插件介绍Tabnine,GsonFormat,Maven Helper等

文章目录 一、Tabnine二、Auto filling Java call arguments三、GsonFormat四、Rainbow Brackets五、Maven Helper 本文主要介绍一些比较实用的IDEA插件,帮助广大开发者提升开发效率,愉悦编码! 一、Tabnine 官网地址:https://ww…

被动元件大厂村田停工近半年 | 百能云芯

据市场传言,受到地震影响,日本被动元件巨头村田的产线,尤其是生产电感的穴水村田制作所,将至少停工至5月中旬。这一消息引发了业界对于台湾厂商是否能够迎来转单效应的猜测。尽管目前转单效益尚不明朗,业内普遍认为&am…

Java项目:10 Springboot的电商书城管理系统

作者主页:源码空间codegym 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 该系统分为前台展示和后台管理两大模块,前台主要是为消费者服务。该子系统实现了注册,登录,以及从浏览、下…

深入详解使用 RabbitMQ 过程中涉及到的多个细节问题(面试可用)

目录 1、基础类问题 2、cluster 相关问题 3、综合性问题 4、参考资料 C软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931C/C基础与进阶&…

商用软件方案的多种交付方式有什么优势?

商用软件方案在交付上,往往存在多种模式,包括SaaS模式、私有化部署、SDK嵌入式等等,SaaS模式讲究一个标准化,旨在最大限度的降低部署成本,但对于一些定制化程度比较高的需求,往往企业仍然需要采用私有化部署…

问题 sr failed: CUDA out of memory. Tried to allocate 解决

一 错误信息:sr failed: CUDA out of memory sr failed: CUDA out of memory. Tried to allocate 370.00 MiB. GPU 0 has a total capacty of 12.00 GiB of which 8.66 GiB is free. Of the allocated memory 969.24 MiB is allocated by PyTorch, and 306.76 MiB …

ubuntu20.04一键通过docker-compose部署mysql 8.0.20

os:ubuntu20.04 docker:v24 docker-compose:v2.2.2 主要步骤 1.拉取镜像 docker pull mysql:8.0.20 2.创建目录 mkdir -p /data/docker_mysql/log mkdir -p /data/docker_mysql/data mkdir -p /data/docker_mysql/conf.d 3.创建配置文…

使用 TurfJS 寻找垂直线

在最近的一个项目中有个需求,我需要确定从单个点 © 到由其他两个点(A 和 B)的连线的垂直距离。通常我们可以只使用turf.nearestPointOnLine(),但是只有当C点位于前两点之间时才有效。 但是点 C 可以在任何位置,不…

axios的基础使用

在阅读本篇文章之前,可以阅读一下这篇文章 json-server的基础使用 因为我们接下来需要使用到json-server 在使用axios之前我们需要导入axios 介绍2种情况: 一、在项目中使用 我们一般都是使用以下两种方法安装 npm i axios yarn add axios二、在普通学习…

HarmonyOS—开发环境诊断的功能

为了大家开发应用/服务的良好体验,DevEco Studio提供了开发环境诊断的功能,帮助大家识别开发环境是否完备。可以在欢迎界面单击Help > Diagnose Development Environment进行诊断。如果已经打开了工程开发界面,也可以在菜单栏单击Help >…

pytest文档35-Hooks函数之统计测试结果(pytest_terminal_summary)

前言 用例执行完成后,我们希望能获取到执行的结果,这样方便我们快速统计用例的执行情况。 也可以把获取到的结果当成总结报告,发邮件的时候可以先统计测试结果,再加上html的报告。 pytest_terminal_summary 关于TerminalReport…