Java的虛擬線程(協(xié)程)特性開(kāi)啟預(yù)覽階段颅和,多線程開(kāi)發(fā)的難度將大大降低

高并發(fā)傅事、多線程一直是Java編程中的難點(diǎn),也是面試題中的要點(diǎn)峡扩。Java開(kāi)發(fā)者也一直在嘗試使用多線程來(lái)解決應(yīng)用服務(wù)器的并發(fā)問(wèn)題蹭越。但是多線程并不容易,為此一個(gè)新的技術(shù)出現(xiàn)了教届,這就是虛擬線程响鹃。

傳統(tǒng)多線程的痛點(diǎn)

但是編寫(xiě)多線程代碼是非常不容易的驾霜,難以控制的執(zhí)行順序,共享變量的線程安全性茴迁,異常的可觀察性等等都是多線程編程的難點(diǎn)寄悯。

如果每個(gè)請(qǐng)求在請(qǐng)求的持續(xù)時(shí)間內(nèi)都在一個(gè)線程中處理,那么為了提高應(yīng)用程序的吞吐量堕义,線程的數(shù)量必須隨著吞吐量的增長(zhǎng)而增長(zhǎng)猜旬。不幸的是線程是稀缺資源,創(chuàng)建一個(gè)線程的代價(jià)是昂貴的倦卖,即使引入了池化技術(shù)也無(wú)法降低新線程的創(chuàng)建成本洒擦,而且 JDK 當(dāng)前的線程實(shí)現(xiàn)將應(yīng)用程序的吞吐量限制在遠(yuǎn)低于硬件可以支持的水平。

為此很多開(kāi)發(fā)人員轉(zhuǎn)向了異步編程怕膛,例如CompletableFuture或者現(xiàn)在正熱的反應(yīng)式框架熟嫩。但是這些技術(shù)要么擺脫不了“回調(diào)地獄”,要么缺乏可觀測(cè)性褐捻。

解決這些痛點(diǎn)掸茅、增強(qiáng)Java平臺(tái)的和諧,實(shí)現(xiàn)每個(gè)請(qǐng)求使用獨(dú)立線程(thread-per-request style)這種風(fēng)格成為必要之舉柠逞。能否實(shí)現(xiàn)一種“成本低廉”的虛擬線程來(lái)映射到系統(tǒng)線程以減少對(duì)系統(tǒng)線程的直接操作呢昧狮?思路應(yīng)該是沒(méi)問(wèn)題的!于是Java社區(qū)發(fā)起了關(guān)于虛擬線程的JEP 425提案板壮。

虛擬線程

虛擬線程(virtual threads)應(yīng)該非常廉價(jià)而且可以無(wú)需擔(dān)心系統(tǒng)硬件資源被大量創(chuàng)建逗鸣,并且不應(yīng)該被池化。應(yīng)該為每個(gè)應(yīng)用程序任務(wù)創(chuàng)建一個(gè)新的虛擬線程绰精。因此撒璧,大多數(shù)虛擬線程將是短暫的并且具有淺層調(diào)用堆棧,只執(zhí)行單個(gè)任務(wù) HTTP 客戶端調(diào)用或單個(gè) JDBC 查詢笨使。與之對(duì)應(yīng)的平臺(tái)線程( Platform Threads卿樱,也就是現(xiàn)在傳統(tǒng)的JVM線程 )是重量級(jí)且昂貴的,因此通常必須被池化硫椰。它們往往壽命長(zhǎng)繁调,有很深的調(diào)用堆棧,并且在許多任務(wù)之間共享最爬。

總而言之,虛擬線程保留了與 Java 平臺(tái)的設(shè)計(jì)相協(xié)調(diào)的门岔、可靠的獨(dú)立請(qǐng)求線程(thread-per-request style)爱致,同時(shí)優(yōu)化了硬件的利用。使用虛擬線程不需要學(xué)習(xí)新概念寒随,甚至需要改掉現(xiàn)在操作多線程的習(xí)慣糠悯,使用更加容易上手的API帮坚、兼容以前的多線程設(shè)計(jì)、并且絲毫不會(huì)影響代碼的拓展性互艾。

平臺(tái)線程和虛擬線程的不同

為了更好理解這一個(gè)設(shè)計(jì)试和,草案對(duì)這兩種線程進(jìn)行了比較。

現(xiàn)在的線程

現(xiàn)在每個(gè)java.lang.Thread都是一個(gè)平臺(tái)線程纫普,平臺(tái)線程在底層操作系統(tǒng)線程上運(yùn)行 Java 代碼阅悍,并在代碼的整個(gè)生命周期內(nèi)捕獲操作系統(tǒng)線程。平臺(tái)線程數(shù)受限于 OS 線程數(shù)昨稼。

平臺(tái)線程并不會(huì)因?yàn)榧尤胩摂M線程而退出歷史舞臺(tái)节视。

未來(lái)的虛擬線程

虛擬線程是由 JDK 而不是操作系統(tǒng)提供的線程的輕量級(jí)實(shí)現(xiàn)。它們是用戶模式線程的一種形式假栓,在其他多線程語(yǔ)言中已經(jīng)成功(比如Golang中的協(xié)程和Erlang中的進(jìn)程)寻行。 虛擬線程采用 M:N 調(diào)度,其中大量 (M) 虛擬線程被調(diào)度為在較少數(shù)量 (N) 的 OS 線程上運(yùn)行匾荆。 JDK 的虛擬線程調(diào)度程序是一種ForkJoinPool工作竊取的機(jī)制拌蜘,以 FIFO 模式運(yùn)行。

我們可以很隨意地創(chuàng)建10000個(gè)虛擬線程:

// 預(yù)覽代碼
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10_000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            return i;
        });
    });
}  

無(wú)需擔(dān)心硬件資源是否扛得住牙丽,反過(guò)來(lái)如果你使用Executors.newCachedThreadPool()創(chuàng)建10000個(gè)平臺(tái)線程简卧,在大多數(shù)操作系統(tǒng)上很容易因資源不足而崩潰。

為吞吐量而設(shè)計(jì)

但是這里依然要說(shuō)明一點(diǎn)剩岳,虛擬線程并是為了提升執(zhí)行速度而設(shè)計(jì)贞滨。它并不比平臺(tái)線程速度快,它們的存在是為了提供規(guī)模(更高的吞吐量)拍棕,而不是速度(更低的延遲)晓铆。它們的數(shù)量可能比平臺(tái)線程多得多,因此根據(jù)利特爾定律绰播,它們可以實(shí)現(xiàn)更高吞吐量所需的更高并發(fā)性骄噪。

換句話說(shuō),虛擬線程可以顯著提高應(yīng)用程序吞吐量

  • 并發(fā)任務(wù)的數(shù)量很高(超過(guò)幾千個(gè))蠢箩,并且

  • 工作負(fù)載不受 CPU 限制链蕊,因?yàn)樵谶@種情況下,擁有比處理器內(nèi)核多得多的線程并不能提高吞吐量谬泌。

虛擬線程有助于提高傳統(tǒng)服務(wù)器應(yīng)用程序的吞吐量滔韵,正是因?yàn)榇祟悜?yīng)用程序包含大量并發(fā)任務(wù),這些任務(wù)花費(fèi)大量的時(shí)間等待掌实。

增強(qiáng)可觀測(cè)性

編寫(xiě)清晰的代碼并不是全部陪蜻。對(duì)正在運(yùn)行的程序狀態(tài)的清晰表示對(duì)于故障排除、維護(hù)和優(yōu)化也很重要贱鼻,JDK 長(zhǎng)期以來(lái)一直提供調(diào)試宴卖、分析和監(jiān)視線程的機(jī)制滋将。 在虛擬線程中也會(huì)增強(qiáng)代碼的可觀測(cè)性,讓開(kāi)發(fā)人員更好地調(diào)試代碼症昏。

新的線程API

為此增加了新的線程API設(shè)計(jì)随闽,目前放出的部分如下:

  • Thread.Builder 線程構(gòu)建器。

  • ThreadFactory 能批量構(gòu)建相同特性的線程工廠肝谭。

  • Thread.ofVirtual() 創(chuàng)建一個(gè)虛擬線程掘宪。

  • Thread.ofPlatform() 創(chuàng)建一個(gè)平臺(tái)線程。

  • Thread.startVirtualThread(Runnable) 一種創(chuàng)建然后啟動(dòng)虛擬線程的便捷方式分苇。

  • Thread.isVirtual() 測(cè)試線程是否是虛擬線程添诉。

還有很多就不一一演示了,有興趣的自行去看JEP425医寿。

總結(jié)

JEP425還有很多的細(xì)節(jié)栏赴,基于我個(gè)人理解能力的不足只能解讀這么多了。協(xié)程在Java社區(qū)已經(jīng)呼喚了很久了靖秩,現(xiàn)在終于有了實(shí)質(zhì)性的動(dòng)作须眷,這是一個(gè)令人振奮的好消息。不過(guò)這個(gè)功能涉及的東西還是很多的沟突,包括平臺(tái)線程的兼容性花颗、對(duì)ThreadLocal的一些影響、對(duì)JUC的影響惠拭±┤埃可能需要多次預(yù)覽才能最終落地。胖哥可能趕不上那個(gè)時(shí)候了职辅,不過(guò)很多年輕的同學(xué)應(yīng)該能夠趕上棒呛。

關(guān)注公眾號(hào):碼農(nóng)小胖哥,獲取更多資訊

個(gè)人博客:https://felord.cn

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末域携,一起剝皮案震驚了整個(gè)濱河市簇秒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌秀鞭,老刑警劉巖趋观,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異锋边,居然都是意外死亡皱坛,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)豆巨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)剩辟,“玉大人,你說(shuō)我怎么就攤上這事∧ɑΓ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵瓤球,是天一觀的道長(zhǎng)融欧。 經(jīng)常有香客問(wèn)我,道長(zhǎng)卦羡,這世上最難降的妖魔是什么噪馏? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮绿饵,結(jié)果婚禮上欠肾,老公的妹妹穿的比我還像新娘。我一直安慰自己拟赊,他們只是感情好刺桃,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著吸祟,像睡著了一般瑟慈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上屋匕,一...
    開(kāi)封第一講書(shū)人閱讀 48,970評(píng)論 1 284
  • 那天葛碧,我揣著相機(jī)與錄音,去河邊找鬼过吻。 笑死进泼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的纤虽。 我是一名探鬼主播乳绕,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼廓推!你這毒婦竟也來(lái)了刷袍?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤樊展,失蹤者是張志新(化名)和其女友劉穎呻纹,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體专缠,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雷酪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涝婉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哥力。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吩跋,到底是詐尸還是另有隱情寞射,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布锌钮,位于F島的核電站桥温,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏梁丘。R本人自食惡果不足惜侵浸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望氛谜。 院中可真熱鬧掏觉,春花似錦、人聲如沸值漫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)杨何。三九已至遵湖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間晚吞,已是汗流浹背延旧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留槽地,地道東北人迁沫。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像捌蚊,于是被迫代替她去往敵國(guó)和親集畅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容