千呼万唤始出来 JDK 21 LTS, 久等了

千呼万唤,出来,jdk,lts,久等 · 浏览次数 : 104

小编点评

**JDK 21 LTS 中的 JAVA 并发编程模型** **简介** JDK 21 LTS 中的 JAVA 并发编程模型是基于虚拟线程的,它比 JDK 19 中的线程池更高效,因为它不再强依赖操作系统内核线程池。 **虚拟线程** 虚拟线程是运行在 JVM 的独立线程,与操作系统内核线程隔离。当使用虚拟线程时,线程与操作系统内核线程之间采用轻量级通信机制,以实现并发编程。 **虚拟线程的优势** - **性能提升:**虚拟线程比线程池具有更高的效率,因为它不需要对操作系统内核线程进行调度。 - **资源利用率降低:**虚拟线程共享 JVM 的内存,减少了创建、切换、销毁等操作所需的内存。 - **线程安全:**虚拟线程使用 Java 语言中的 volatile 设计模式,确保数据一致性。 **虚拟线程的局限性** - **内存消耗:**创建和管理虚拟线程可能需要更多的内存空间。 - **上下文切换成本:**虚拟线程切换操作比线程切换操作更昂贵。 **与线程池比较** 线程池是使用线程池管理创建和销毁线程的机制。线程池会根据需要创建和销毁线程,以优化性能。但是,线程池通常与操作系统内核线程池一起使用,可能导致资源竞争。 **结论** JDK 21 LTS 中的虚拟线程是一种高效的并发编程模型,可以有效提升应用程序的性能。然而,虚拟线程也有一些局限性,需要在内存利用率和性能之间进行权衡。

正文

平地起惊雷!!!

你可以称呼它为:JDK 8 之后的神,它也是很多人认为的 JDK 8 之后,最值得升级的版本。

以前大家都说:

他发任他发,我用JAVA 8

抱歉,这次JDK 21 我不得不使用了


已知使用较为广泛的几个 LTS版本是 (Long Term Support) :

  • JDK 8 LTS
  • JDK 11 LTS
  • JDK 17 LTS

那么为什么非得是 JDK 21呢?

英雄的迟暮

  • ...
  • Kafka 宣布弃用 Java 8 ...
  • Jenkins 宣布弃用 Java 8 ...
  • Spring6 强依赖 Java 17 ...
  • Elasticsearch 使用的JDK 也不是 JDK8
  • ......

JDK 8 的地位并非无可撼动的,如下所示为某个机构统计的,近几年一些线上 JAVA 应用使用的 JDK 版本情况:

  • LTS j8 已经从 84% 一路迭到了 32%

  • 而另两个 LTS 版本 J_11 和 J_17 的使用情况都有了长足的进步

所以别傻了,可能只有你在坚守JDK 8,你的小伙伴可能都已经转投别人温暖的怀抱了

JDK 21 LTS 可是迎来了史诗级的增强(后边详述),它的表现一定不会比 JDK_11 和 JDK_17弱。

spring系列作为绑定JAVA的头号玩家,期待 Spring 的下一个大版本。

变革的大幕已经拉开,车轮已经开始滚滚先前; 昨日之日或西垂,夺目新日将大展光芒。

大人时代变了

JDK 21他来真的了,下边是我们的主角闪亮登场:

曾经在JDK 19中作为预览的虚拟线程,在JDK 21 LTS 中成为正式功能了

[PS * JDK 21 除了 虚拟线程 ,其实还有不少别的特性,但是我感觉都属于真正的平平无奇的水平,只有 虚拟线程 值得大动干戈。]

犹记得曾经阅读读 《深入理解Java虚拟机》一书时,关于Java 并发编程模型的章节,了解了 JAVA 的并发编程模型现状后,纯纯的 GoLang 薄纱啊,故此实引为一大遗憾。当时书中提到 JAVA 官方启动了 Loom 项目来弥补这一缺憾,当时都只觉得是在忽悠,这么多年的问题了,哪儿能那么容易解决呢,怕是画了老大一个饼吧? 虽然是耿耿于怀,之后老长时间没有关注它了,然后,突然某天看到JDK 21来了, 虚拟线程 成为了正式功能了,当时看到这个消息时还是挺开心的

问题一: 不就是上下文切换么,我配置好线程池不就够了?

  • 设置线程池在一定程度上,确实可以减少上下文切换,但是除了创建线程、线程销毁,线程的生命周期中的其它操作呢?

问题二,屎山怎么办?

  • 屎山没必要动它,原样维持呗,可别给我说你本地装了 j21 之后j8 的项目就没办法跑起来了
  • 而且现在【微服务 + 容器平台】那么火爆,这同样也是解决之道啊

JDK 21 LTS 前 JAVA并发编程模型

JAVA 21之前的版本,用户态(JVM 态)下,JDK的并发编程模型的是,JVM线程与操作系统的内核线程 1:1 实现,缺点是在用户态(JVM态)下的每一个线程的,挂起、唤醒、销毁等调度操作,都会直接作用到操作系统的内核线程上。

  • LWP (Light Weight Process) 轻量级进程, 也就是JDK 21 之前版本中 JAVA 线程了
  • KLT (kernel Level Thread) 操作线程内核线程

LWP 与 KLT 之间是一对一的

从JVM 发起对内核线程的调度,相对来说是一个非常重的操作,资源消耗严重。

关于资源消耗,例如:

  • LWP (轻量级进程) 会消耗一定的内核资源,比如内核线程的栈空间,因此操作系统支持的轻量级进程是有限的。
  • 高损耗的内核线程调度,它直接影响高并发场景下,多个线程的执行效率,所以之前偶尔听到流传的一个说法: Java业务为王,GoLang高并发称雄。

JDK 21 LTS 中的 JAVA 并发编程模型

而到了JDK 21 LTS 中引入的 虚拟线程 呢,到了这里并发编程模型的实现发生了变化:

JVM 态线程跟操作系统内核态线程不再 {1:1} 实现,而是 { [1 (操作系统内核线程)] : [N (JVM 虚拟线程 )] }。这样在JVM态下,对每个 虚拟线程 的创建、调度、切换、销毁等操作,不再直接高度依赖操作系统内核线程,所以高并发场景下,线程的执行效率会有很大提升。

  • UT: user thread 用户线程,也可以称呼它:虚拟线程

其实 GoLang 的协程就是类似 虚拟线程 的东西;不过 JAVA 的 虚拟线程 跟 GoLang 的协程还是有区别的:

  • GoLang 的协程支持跨核(cpu),内存管理更优
  • Java 的虚拟线程不支持跨核,但是执行的效率更佳

具体要怎么选择,就是仁者见仁智者见智了。




回到前边提到的关于线程池的问题上来

虚拟线程 VS 线程池

先明确两个概念:

  - 轻量级进程:也就是 JDK 21 之前的 JAVA 线程,它的上下文切换直接关联到操作系统内核上。

  - 虚拟线程:JDK 21 新特性,纯JVM 用户态下的东西,它的执行、调度... 等操作不会强关联系统内核

线程池大行其道的原因:

  • 每个 轻量级进程 的创建,都会直接去操作,操作系统的内核线程,并竞争CPU 的时间分片。所以聪明的大佬们想到了一个办法就是引入线程池,这样就可以大量节省去调度操作系统内核线程,执行 轻量级进程 创建、线程注销相关的操作开销了。

  • JDK 21 之前 轻量级进程 自身占用的内存很高,也是线程池能够大行其道的原因之一,常见的64位的操作系统上一个 轻量级进程 默认占用 1MB 的内存空间。

但是即使有了线程池,还是指标不治本。 轻量级进程 除了创建、销毁之外,还有:挂起、唤醒 ...... 等等一系列的操作的上下文切换还是要依赖操作系统内核来完成的。由于线程池是复用的,线程池的每个 轻量级进程 会经历无数次的挂起、唤醒、执行CPU 时间分片, 直至 轻量级进程 被线程池剔除。

然后就是 虚拟线程 了,它彻底解决了这些难点问题:

  • 基于用户态实现的并发编程模型,决定了 虚拟线程 调度,不再强依赖系统内核
  • 虚拟线程 空间占用极小,默认只有几百字节;设备同等内存大小时,创建的 虚拟线程 数很搞不好可以达到 轻量级进程 数的指数倍。

The Last

总结来说就是:

减少了直接对操作系统内核线程的调度,将并发模型从操作系统内核 {1:1} 实现,转变为 {1:N} 实现,虚拟线程将完全由 JVM 自管理,执行效率,资源利用率都将得到提升。

综上所述直接吹爆 JDK 21,因为从 虚拟线程 开始,Java 在高并发领域也获得了入场券。越是了解JVM 并发编程的模型的人,越会知道 虚拟线程 的重量。

连挤牙膏式的 JDK 11 LTS 和 JDK 17 LTS 使用量都能上去,凭什么作为王牌的 JDK 21 LTS 会上不去?




从旧线程迁移到虚拟线程需要注意的事项

1、忘记线程池,旧时代的良药,新时代的糟粕罢了。

2、慎用 ThreadLocal 尤其是高并发场景,如果不能合理使用它,搞不好就是内存溢出。

与千呼万唤始出来 JDK 21 LTS, 久等了相似的内容:

千呼万唤始出来 JDK 21 LTS, 久等了

平地起惊雷!!! 目录英雄的迟暮大人时代变了JDK 21 LTS 前 JAVA并发编程模型JDK 21 LTS 中的 JAVA 并发编程模型虚拟线程 VS 线程池The Last 你可以称呼它为:JDK 8 之后的神,它也是很多人认为的 JDK 8 之后,最值得升级的版本。 以前大家都说: 他发任他

千万别忽视基础!十张图带你一步步理解Java内存结构!

发生内存泄漏或者内存溢出,如果对Java内存结构不清楚,那将会是一件非常麻烦的事情!本文笔者将为大家详解Java内存结构。

千万级流量冲击下,如何保证极致性能

1 简要介绍 随着互联网的快速发展,网络应用的流量规模不断攀升,特别是在电商大促、明星直播、重大赛事、头条热搜等热点事件中,秒级100w请求成为了常态。在这样的流量冲击下,如何确保系统稳定、高效地处理每一个请求,为用户提供极致的体验,成为了技术团队面临的重要挑战。本文将深入探讨在超高流量下如何保证系

千万级数据深分页查询SQL性能优化实践

最近接到了一个新需求,要求提供查询关注对象的粉丝列表接口功能。该功能的难点就是关注对象的粉丝数量过多,不少店铺的粉丝数量都是千万级别,并且有些大V粉丝数量能够达到上亿级别

[转帖]mysql 千万数据迁移的几种方式

最近因为业务需求,我们需要将我们的订单表(一千三百万数据,并且每天已五万条速度增加)已订单类型分组迁移到新的业务表中,以降低我们订单表的大小,同时暂时杜绝订单表所带来的数据瓶颈问题,需求下来了,基本思路也要确定下来,我打算先将三天前的历史数据先跑到表里,待整个业务线迁移过后,我再将剩下的数据跑进去,

前端说你的API接口太慢了,怎么办?

当有千万条海量数据时,前端调取接口发现接口响应的太慢,前端这时让你优化一下接口,你说有几千万条数据,觉得自己尽力了,前端觉得你好菜,别急,读完这篇文章,让前端喊你一声:大佬,厉害!!! 常用的方法总结 通过合理的分页加载、索引优化、数据缓存、异步处理、压缩数据等手段,可以有效地优化接口性能,提升系统

win11添加开机自启动

方法1 win + R 打开运行,输入 shell:startup 会打开一个文件夹 将想要启动的程序快捷方式放进文件夹 在设置里面搜索“启动”,可以看到开机启动项,确认已经打开。 以上,针对不用管理员权限启动的程序,有效。 方法2 下面看需要管理员权限的: 按Win+R,输入regedit,打开注

稳定支撑千万级月活,华为日历背后的英雄

摘要:华为日历月活高达数千万,这使其对支撑业务的数据库提出了巨大挑战:高并发场景下,数据库如何实现快速扩容?海量数据运行,如何确保业务稳定性? 本文分享自华为云社区《稳定支撑千万级月活,华为日历背后的英雄》,作者: GaussDB 数据库。 随着科技进步,手机日历早已融入我们的生活,不仅可以记录时间

如何实现千万级优惠文章的优惠信息同步

金融社区优惠文章是基于京东商城优惠商品批量化自动生成的,每日通过不同的渠道获取到待生成的SKU列表,并根据条件生成优惠文章。 但是,生成优惠文章之后续衍生问题:该商品无优惠了,对应文章需要做取消推荐或下架处理,怎样能更快的知道该商品无优惠了呢?

交易日均千万订单的存储架构设计与实践

服务业务线:快递、快运、中小件、大件、冷链、国际、B2B合同物流、CLPS、京喜、三入三出(采购入、退货入、调拨入、销售出、退供出、调拨出)等