千呼萬喚始出來 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 時間分片, 直至 輕量級進程 被線程池踢除。

然後就是 虛擬線程 了,它徹底解決了這些難點問題:

  • 基於用戶態實現的併發編程模型,決定了 虛擬線程 調度,不再強依賴系統內核
  • 虛擬線程 空間佔用極小,默認只有幾百字節,在64位的系統上,比 輕量級進程 默認的 1MB 小了太多太多;同等內存佔用下,創建的 虛擬線程 數絕對很容易達到 輕量級進程 數的指數倍。

The Last

總結來說就是:

減少了直接對操作系統內核線程的調度,將併發模型從操作系統內核 {1:1} 實現,轉變爲 {1:N} 實現,虛擬線程將完全由 JVM 自管理,執行效率,資源利用率都將得到提升。

綜上所述直接吹爆 JDK 21,因爲從 虛擬線程 開始,Java 在高併發領域也獲得了入場券。越是瞭解JVM 併發編程的模型的人,越會知道 虛擬線程 的重量。

連擠牙膏式的 JDK 11 LTSJDK 17 LTS 使用量都能上去,憑什麼作爲王牌的 JDK 21 LTS 會上不去?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章