一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

什么是虛擬線程?虛擬線程到底是做什么用的呢?

OSC開(kāi)源社區(qū) ? 來(lái)源:程序猿DD ? 2023-10-29 10:23 ? 次閱讀

什么是虛擬線程

虛擬線程是在Java并發(fā)領(lǐng)域添加的一個(gè)新概念,那么虛擬線程到底是做什么用的呢?

根據(jù)JEP中的內(nèi)容告訴我們,虛擬線程是一種輕量級(jí)線程,可以顯著地幫助我們減少編寫(xiě)、維護(hù)、觀察高吞吐量應(yīng)用程序的工作量。它的實(shí)現(xiàn)目標(biāo)有以下幾點(diǎn):

每個(gè)請(qǐng)求一個(gè)線程風(fēng)格編寫(xiě)的程序,能夠以接近最佳硬件利用率進(jìn)行擴(kuò)展。

什么是每個(gè)請(qǐng)求一個(gè)線程的風(fēng)格?

對(duì)于HTTP服務(wù)器來(lái)說(shuō),這意味著每個(gè)HTTP請(qǐng)求都由它自己的線程處理。對(duì)于關(guān)系型數(shù)據(jù)庫(kù)服務(wù)器來(lái)說(shuō),這意味著每個(gè)SQL事務(wù)也都由它自己的線程處理。如果您曾經(jīng)使用過(guò) Java EE 服務(wù)器,那么它就是這樣工作的。所以,什么是每個(gè)請(qǐng)求一個(gè)線程的風(fēng)格就是:一個(gè)請(qǐng)求 = 一個(gè)事務(wù) = 一個(gè)線程。

bca3e94a-7565-11ee-939d-92fbcf53809c.png

那么,這個(gè)模型的成本是多少呢? 要了解這個(gè)成本,您需要了解 Java 中線程的成本。平臺(tái)線程和 CPU 使用率的成本。

Java 線程是在 Java 的早期版本中創(chuàng)建的,屬于平臺(tái)線程,也稱為操作系統(tǒng)線程上的薄包裝器。關(guān)于它們,您需要了解兩件事。

平臺(tái)線程需要將其調(diào)用堆棧存儲(chǔ)在內(nèi)存中

它是系統(tǒng)資源,啟動(dòng)平臺(tái)線程大約需要一毫秒

事實(shí)上,平臺(tái)線程是一種相當(dāng)昂貴的資源。如何利用此類線程優(yōu)化硬件利用率呢?

假設(shè)您的應(yīng)用程序有 16 GB 的可用內(nèi)存。除以 20 MB 的線程大小,這樣的機(jī)器上就有 800 個(gè)線程的空間。假設(shè)這些線程正在執(zhí)行一些 I/O,就像訪問(wèn)網(wǎng)絡(luò)上的資源一樣。假設(shè)該資源在 100 毫秒內(nèi)被訪問(wèn)。準(zhǔn)備請(qǐng)求和處理響應(yīng)將在 10 納秒的時(shí)間內(nèi)完成。假設(shè)所有這些內(nèi)存計(jì)算需要 1000 納秒。這意味著在準(zhǔn)備請(qǐng)求和處理響應(yīng)之間存在一個(gè)大約 100000 的因素,以及獲得響應(yīng)所需的時(shí)間,在此期間您的線程就在那里什么都不做。所以如果你有 800 個(gè)這樣的線程,那么CPU利用率只有可憐的0.8%。

bcb39016-7565-11ee-939d-92fbcf53809c.png

如果你將內(nèi)存加倍到 32 GB,那么CPU利用率可以達(dá)到1.3%,但這仍然很低。

bcbcc924-7565-11ee-939d-92fbcf53809c.png

反過(guò)來(lái)思考下,如果我們希望達(dá)到90%的CPU利用率。那么就需要 90000 個(gè)線程,啟動(dòng)它們需要 90秒,同時(shí),還要消耗 1.8 TB 的內(nèi)存。

bcc12488-7565-11ee-939d-92fbcf53809c.png

很明顯,平臺(tái)線程的成本太高,無(wú)法以接近最佳的硬件利用率進(jìn)行擴(kuò)展。因此,我們需要另一種線程模型來(lái)解決這樣的問(wèn)題。

使基于經(jīng)典 Java 線程的現(xiàn)有代碼能夠以最小更改代價(jià)來(lái)使用虛擬線程

這一目標(biāo)意味著可以把經(jīng)典線程做的所有事情,輕松的轉(zhuǎn)換為虛擬線程的處理方式來(lái)完成。這里涵蓋了幾個(gè)關(guān)鍵點(diǎn)。

虛擬線程可以運(yùn)行任何Java代碼或任何本機(jī)代碼。

你不需要學(xué)習(xí)任何新概念。

但你需要忘掉某些想法,比如:

虛擬線程很便宜,比傳統(tǒng)平臺(tái)線程便宜大約 1,000 倍。

阻塞虛擬線程的成本也很低,因此試圖避免阻塞虛擬線程是沒(méi)有用的。

編寫(xiě)經(jīng)典的阻塞代碼是可以的,這是一個(gè)好消息,因?yàn)樽枞a比異步代碼更容易編寫(xiě)。此時(shí),您可能想知道,池化虛擬線程是個(gè)好主意嗎?嗯,答案是否定的。不要那樣做。你只是在浪費(fèi)時(shí)間。

關(guān)于虛擬線程還有兩個(gè)好消息:線程局部變量也以同樣的方式工作;同步也有效。關(guān)于同步有幾件事需要說(shuō)一下。虛擬線程仍然運(yùn)行在平臺(tái)線程之上,下面還有一個(gè)平臺(tái)線程。不過(guò),這個(gè)虛擬線程可以與其平臺(tái)線程分離,以便這個(gè)平臺(tái)線程可以運(yùn)行另一個(gè)虛擬線程。什么時(shí)候才能脫離呢?虛擬線程一旦阻塞就可以與其平臺(tái)線程分離。它可能會(huì)在I/O操作或同步操作上被阻止,或者可能會(huì)被置于睡眠狀態(tài)。如果虛擬線程正在同步塊內(nèi)執(zhí)行某些代碼,則它無(wú)法與其平臺(tái)線程分離。

因此,在運(yùn)行此同步代碼塊期間,它會(huì)阻塞平臺(tái)線程。如果這個(gè)時(shí)間很短,那也沒(méi)關(guān)系。無(wú)需恐慌,也無(wú)需采取任何措施來(lái)防止這種情況發(fā)生。如果這個(gè)時(shí)間很長(zhǎng),也就是說(shuō),如果它正在做一些長(zhǎng)時(shí)間的I/O操作,那么情況就不太好了。您可以通過(guò)簡(jiǎn)單地將對(duì) synchronized 的調(diào)用替換為可重入鎖來(lái)防止這種情況發(fā)生。

深入研究編碼

關(guān)于如何創(chuàng)建虛擬線程,在之前的Java 21新特性虛擬線程中有提到。通過(guò)Thread.ofVirtual()即可,比如:

Thread.ofVirtual()
.name("didispace-virtual-thread")
.start(runnable);

Tips:如果要?jiǎng)?chuàng)建平臺(tái)線程,則可使用:Thread.ofPlatform()

虛擬線程工作在平臺(tái)線程之上。您可能認(rèn)為沒(méi)有任何性能提升,只是產(chǎn)生了開(kāi)銷。那么到底是怎么回事呢?關(guān)于虛擬線程還有更多內(nèi)容。下面一起來(lái)看看這段代碼是如何運(yùn)行的。

bcce6c10-7565-11ee-939d-92fbcf53809c.png

這段代碼中,使用了流模式創(chuàng)建 10 個(gè)虛擬的、未啟動(dòng)的線程。這些線程正在運(yùn)行的任務(wù)只是打印當(dāng)前線程。然后,讓它們休眠 10 毫秒,接著再次打印線程的名稱。最后,啟動(dòng)這些未啟動(dòng)的線程并調(diào)用 join 方法以確保所有內(nèi)容都可以在控制臺(tái)上看到。

那么運(yùn)行這段代碼,您會(huì)發(fā)現(xiàn)這里發(fā)生了一些真正意想不到的事情。

bcd2911e-7565-11ee-939d-92fbcf53809c.png

這個(gè)ForkJoinPool的線程7,當(dāng)它從睡眠狀態(tài)回來(lái)時(shí),它并沒(méi)有繼續(xù)運(yùn)行在原來(lái)的平臺(tái)線程上,而是跳轉(zhuǎn)到了另外一個(gè)平臺(tái)線程。如果您在自己的計(jì)算機(jī)上執(zhí)行此操作,請(qǐng)確保啟動(dòng)足夠的虛擬線程,因?yàn)槟赡懿粫?huì)僅使用一兩個(gè)線程來(lái)觀察到這一點(diǎn)。

它在幕后是如何工作的

事實(shí)上,當(dāng)虛擬線程由于某些操作而被阻塞時(shí),相應(yīng)的堆棧就會(huì)從其運(yùn)行的平臺(tái)線程移動(dòng)到堆內(nèi)存中。所以,現(xiàn)在這個(gè)平臺(tái)線程可以自由地運(yùn)行另一個(gè)虛擬線程。當(dāng)這個(gè)任務(wù)收到可以繼續(xù)運(yùn)行的信號(hào)時(shí),它的堆棧就會(huì)從堆移回平臺(tái)線程,但不一定相同。所以,這就是阻塞虛擬線程的代價(jià),將該虛擬線程的堆棧移動(dòng)到主內(nèi)存并返回。阻塞虛擬線程并不是免費(fèi)無(wú)開(kāi)銷的,但它比阻塞平臺(tái)線程要?jiǎng)澦愕枚唷?/p>

Tips:這段邏輯視頻里有圖形化的解釋,推薦結(jié)合視頻動(dòng)畫(huà)觀看,會(huì)更容易理解。

令人高興的是,JDK 的所有阻塞操作都已被重構(gòu)以利用它。其中包括I/O操作、同步和Thread.sleep。

需要多少平臺(tái)線程來(lái)運(yùn)行虛擬線程

bcd6dcb0-7565-11ee-939d-92fbcf53809c.png

關(guān)于這個(gè)問(wèn)題,我們可以測(cè)試一下。讓我創(chuàng)建虛擬線程并收集所有相應(yīng)的平臺(tái)線程名稱。

bce4e12a-7565-11ee-939d-92fbcf53809c.pngbce925fa-7565-11ee-939d-92fbcf53809c.png

該代碼基本上啟動(dòng)了五個(gè)虛擬線程,然后使用一些代碼提取池名稱和平臺(tái)線程名稱。最后,它只是打印不同的統(tǒng)計(jì)信息、運(yùn)行此代碼所需的時(shí)間、CPU 上的核心數(shù)量、線程池?cái)?shù)量,以及平臺(tái)線程的數(shù)量。

那么讓我運(yùn)行這段代碼,可以看到如下結(jié)果:

bcf4920a-7565-11ee-939d-92fbcf53809c.png

對(duì)于 5 個(gè)虛擬線程,它使用 3 個(gè)平臺(tái)線程并花費(fèi) 2 毫秒。

讓我使用 10 個(gè)虛擬線程并再次運(yùn)行代碼。

bd00b09e-7565-11ee-939d-92fbcf53809c.png

對(duì)于 10 個(gè)線程,它仍然使用 3 個(gè)平臺(tái)線程并花費(fèi)了 4 毫秒。

讓我使用 100 個(gè)虛擬線程并再次運(yùn)行代碼。

bd0801aa-7565-11ee-939d-92fbcf53809c.png

現(xiàn)在它使用 7 個(gè)平臺(tái)線程。

讓我們看看 1,000 個(gè)虛擬線程會(huì)發(fā)生什么。

bd0c2ff0-7565-11ee-939d-92fbcf53809c.png

它仍然使用 7 個(gè)平臺(tái)線程。

試試10萬(wàn)個(gè)虛擬線程怎么樣?

bd14389e-7565-11ee-939d-92fbcf53809c.png

現(xiàn)在它使用 8 個(gè)平臺(tái)線程,花費(fèi)了 156 毫秒。

順便說(shuō)一句,即使這些線程沒(méi)有做太多事情,只是一些字符串操作和在并發(fā)集中添加元素,您也可以看到運(yùn)行所有這些線程只需要 156 毫秒。

現(xiàn)在讓我增加到 100 萬(wàn)個(gè)線程。

bd17f038-7565-11ee-939d-92fbcf53809c.png

花費(fèi)了不到一秒的時(shí)間,并且仍然使用 8 個(gè)平臺(tái)線程。

如果您學(xué)習(xí)過(guò)程中如遇困難?可以加入我們超高質(zhì)量的技術(shù)交流群,參與交流與討論,更好的學(xué)習(xí)與進(jìn)步!另外,不要走開(kāi),關(guān)注我!持續(xù)更新Java新特性專欄!

啟動(dòng)1000萬(wàn)個(gè)虛擬線程

我們嘗試啟動(dòng) 1000 萬(wàn)個(gè)虛擬線程怎么樣?你曾經(jīng)嘗試過(guò)這樣做嗎?在您的機(jī)器上啟動(dòng) 1000 萬(wàn)個(gè)平臺(tái)線程?嗯,通常這是不可能的,但是使用虛擬線程,我們也許能夠做到。我們可以獲得如下結(jié)果:

bd1b8a9a-7565-11ee-939d-92fbcf53809c.png

這還只是在一臺(tái)舊筆記本電腦上測(cè)試的結(jié)果,只需要不到 7 秒的時(shí)間,這真是太棒了!

這就是Java 中的虛擬線程!是不是很棒?那么,你是否已經(jīng)開(kāi)始升級(jí)Java 21并開(kāi)始使用此特性來(lái)提升你的應(yīng)用性能了呢?留言區(qū)一起聊聊吧。






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    20

    文章

    2983

    瀏覽量

    106499
  • SQL
    SQL
    +關(guān)注

    關(guān)注

    1

    文章

    779

    瀏覽量

    44705
  • 虛擬機(jī)
    +關(guān)注

    關(guān)注

    1

    文章

    955

    瀏覽量

    28878

原文標(biāo)題:什么是虛擬線程?一次啟1000萬(wàn)個(gè)會(huì)OOM嗎?

文章出處:【微信號(hào):OSC開(kāi)源社區(qū),微信公眾號(hào):OSC開(kāi)源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Spring Boot虛擬線程和Webflux性能對(duì)比

    早上看到一篇關(guān)于Spring Boot虛擬線程和Webflux性能對(duì)比的文章,覺(jué)得還不錯(cuò)。內(nèi)容較長(zhǎng),抓重點(diǎn)給大家介紹一下這篇文章的核心內(nèi)容,方便大家快速閱讀。
    發(fā)表于 09-24 14:54 ?1122次閱讀
    Spring Boot<b class='flag-5'>虛擬</b><b class='flag-5'>線程</b>和Webflux性能對(duì)比

    ic618+spectre18+calibre2019虛擬機(jī)到底是什么?

    ic618+spectre18+calibre2019虛擬機(jī)到底是什么?有什么作用?
    發(fā)表于 06-22 08:00

    Linux系統(tǒng)的線程到底是什么

    在嵌入式操作系統(tǒng)中,任務(wù)相當(dāng)于Linux系統(tǒng)的線程。在所有的操作系統(tǒng)中,線程(在嵌入式操作系統(tǒng)中一般稱為任務(wù))是一個(gè)單一順序的執(zhí)行流,是分配運(yùn)行資源(CPU的運(yùn)行時(shí)間)的基本單位。操作系統(tǒng)根據(jù)一定
    發(fā)表于 12-21 07:27

    線程好還是單線程好?單線程和多線程的區(qū)別 優(yōu)缺點(diǎn)分析

    摘要:如今單線程與多線程已經(jīng)得到普遍運(yùn)用,那么到底線程好還是單線程好呢?單線程和多
    發(fā)表于 12-08 09:33 ?8.2w次閱讀

    CPU與核心及進(jìn)程和線程認(rèn)識(shí)

    所謂的4核8線程,4核指的是物理核心。通過(guò)超線程技術(shù),一個(gè)物理核模擬兩個(gè)虛擬核,每個(gè)核兩個(gè)線程,總數(shù)為8
    的頭像 發(fā)表于 03-30 14:48 ?8229次閱讀
    CPU與核心及進(jìn)程和<b class='flag-5'>線程</b>認(rèn)識(shí)

    基于STM32的虛擬線程(TI_BLE協(xié)議棧_ZStack協(xié)議棧)

    基于STM32的虛擬線程,可以很好的用于裸機(jī)程序中,用于模擬小型操作系統(tǒng)的多線程概念。本實(shí)例參考了參考TI_BLE協(xié)議棧_ZStack協(xié)議棧。
    發(fā)表于 06-14 10:42 ?7040次閱讀
    基于STM32的<b class='flag-5'>虛擬</b>多<b class='flag-5'>線程</b>(TI_BLE協(xié)議棧_ZStack協(xié)議棧)

    虛擬內(nèi)存有什么用

    虛擬內(nèi)存有什么用?雖說(shuō)內(nèi)存的大小會(huì)直接影響我們電腦的運(yùn)行的程序個(gè)數(shù)和運(yùn)行速度,但是當(dāng)內(nèi)存的容量剩余很少的時(shí)候,再運(yùn)行電腦程序的時(shí)候,電腦就會(huì)變得很卡。但是有了虛擬內(nèi)存,這樣能夠臨時(shí)的使內(nèi)存變大,可以讓我們使用的電腦運(yùn)行更多的電腦
    的頭像 發(fā)表于 03-14 14:55 ?1.5w次閱讀

    虛擬機(jī):查看linux線程的CPU占用率的方法

    虛擬機(jī):查看linux線程的CPU占用率的方法
    的頭像 發(fā)表于 06-22 10:06 ?4253次閱讀
    <b class='flag-5'>虛擬</b>機(jī):查看linux<b class='flag-5'>線程</b>的CPU占用率的方法

    虛擬機(jī):linux 進(jìn)程的最大線程個(gè)數(shù)

    虛擬機(jī):linux 進(jìn)程的最大線程個(gè)數(shù)
    的頭像 發(fā)表于 06-22 15:56 ?2908次閱讀
    <b class='flag-5'>虛擬</b>機(jī):linux 進(jìn)程的最大<b class='flag-5'>線程</b>個(gè)數(shù)

    虛擬機(jī):Linux查看線程信息的步驟

    虛擬機(jī):Linux查看線程信息的步驟
    的頭像 發(fā)表于 06-24 08:41 ?3669次閱讀
    <b class='flag-5'>虛擬</b>機(jī):Linux查看<b class='flag-5'>線程</b>信息的步驟

    探究到底什么是虛擬技術(shù)

    那么虛擬化技術(shù)到底是什么?其實(shí)廣義上來(lái)說(shuō),就是通過(guò)映射或抽象的方式屏蔽物理設(shè)備復(fù)雜性。它可以有效簡(jiǎn)化基
    發(fā)表于 03-15 14:43 ?3974次閱讀

    雙面金屬化聚丙烯膜電容到底是做什么用的?

    所謂聚丙烯電容,指的就是CBB電容器,但CBB電容種類還是極多的,其中有一個(gè)非常特殊的電容器,那就是雙面金屬化聚丙烯膜電容,它的簡(jiǎn)稱是MMKP82電容,雙面金屬化聚丙烯膜電容到底是做什么用的?
    發(fā)表于 11-24 11:40 ?1397次閱讀

    濾波器到底是什么?濾波有什么用?

    在關(guān)于雷達(dá)原理的說(shuō)明中,經(jīng)常見(jiàn)到各種濾波器的描述,那濾波器到底是什么?
    的頭像 發(fā)表于 05-24 11:12 ?4403次閱讀

    Spring Boot 3.2支持虛擬線程和原生鏡像

    Spring Boot 3.2 前幾日發(fā)布,讓我們 Java 21、GraalVM 和虛擬線程來(lái)嘗試一下。
    的頭像 發(fā)表于 11-30 16:22 ?893次閱讀

    探索虛擬線程:原理與實(shí)現(xiàn)

    虛擬線程的引入與優(yōu)勢(shì) 在Loom項(xiàng)目之前,Java虛擬機(jī)(JVM)中的線程是通過(guò)java.lang.Thread類型來(lái)實(shí)現(xiàn)的,這些線程被稱為
    的頭像 發(fā)表于 06-24 11:35 ?485次閱讀
    探索<b class='flag-5'>虛擬</b><b class='flag-5'>線程</b>:原理與實(shí)現(xiàn)