日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
Java21的虛擬線(xiàn)程:高性能并發(fā)應(yīng)用的福音

Java 21 最重要的特性之一就是虛擬線(xiàn)程 (JEP 444)。這些輕量級(jí)的線(xiàn)程降低了編寫(xiě)、維護(hù)和觀察高吞吐量并行應(yīng)用所需的努力。

網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)!專(zhuān)注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、小程序開(kāi)發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶(hù)創(chuàng)新互聯(lián)還提供了建湖免費(fèi)建站歡迎大家使用!

在討論新特性之前,讓我們先看一下當(dāng)前的狀態(tài),以便更好地理解它試圖解決什么問(wèn)題以及帶來(lái)了哪些好處。

平臺(tái)線(xiàn)程

在引入虛擬線(xiàn)程之前,我們習(xí)慣使用的線(xiàn)程是 java.lang.Thread,它背后是所謂的平臺(tái)線(xiàn)程 (platform threads)。

這些線(xiàn)程通常與操作系統(tǒng)調(diào)度的內(nèi)核線(xiàn)程一一映射。操作系統(tǒng)線(xiàn)程相當(dāng)“重”,這使得它們適合執(zhí)行所有類(lèi)型的任務(wù)。

根據(jù)操作系統(tǒng)和配置,它們默認(rèn)情況下會(huì)消耗大約2到10 MB的內(nèi)存。因此,如果你想在高負(fù)載并發(fā)應(yīng)用程序中使用一百萬(wàn)個(gè)線(xiàn)程,最好要有超過(guò)2 TB的可用內(nèi)存!

這存在一個(gè)明顯的瓶頸,限制了我們實(shí)際可以在沒(méi)有缺點(diǎn)的情況下?lián)碛械木€(xiàn)程數(shù)量。

每個(gè)請(qǐng)求一個(gè)線(xiàn)程

這很成問(wèn)題,因?yàn)樗苯优c典型的服務(wù)器應(yīng)用程序“每個(gè)請(qǐng)求一個(gè)線(xiàn)程”的方法相沖突。使用每個(gè)請(qǐng)求一個(gè)線(xiàn)程有很多優(yōu)點(diǎn),例如更簡(jiǎn)單的狀態(tài)管理和清理。但它也創(chuàng)造了可擴(kuò)展性限制。應(yīng)用程序的“并發(fā)單位”,在這種情況下是一個(gè)請(qǐng)求,需要一個(gè)“平臺(tái)并發(fā)單位”。因此,線(xiàn)程很容易被原始CPU能力或網(wǎng)絡(luò)耗盡。

即使“每個(gè)請(qǐng)求一個(gè)線(xiàn)程”有許多優(yōu)點(diǎn),共享重量級(jí)的線(xiàn)程可以更均勻地利用硬件,但也需要一種完全不同的方法。

異步救援

而不是在單個(gè)線(xiàn)程上運(yùn)行整個(gè)請(qǐng)求,它的每個(gè)部分都從池中使用一個(gè)線(xiàn)程,當(dāng)它們的任務(wù)完成時(shí),另一個(gè)任務(wù)可能會(huì)重用同一個(gè)線(xiàn)程。這允許代碼需要更少的線(xiàn)程,但引入了異步編程的負(fù)擔(dān)。

異步編程伴隨著它自己的范例,具有一定的學(xué)習(xí)曲線(xiàn),并且可能會(huì)使程序更難理解和跟蹤。請(qǐng)求的每個(gè)部分可能都在不同的線(xiàn)程上執(zhí)行,從而創(chuàng)建沒(méi)有合理上下文的堆棧跟蹤,并使調(diào)試某些內(nèi)容變得非常棘手甚至幾乎不可能。

Java有一個(gè)用于異步編程的優(yōu)秀API,CompletableFuture。但這是一個(gè)復(fù)雜的API,并且不太適合許多Java開(kāi)發(fā)人員習(xí)慣的思維方式。

重新審視“每個(gè)請(qǐng)求一個(gè)線(xiàn)程”模型,很明顯,一種更輕量級(jí)的線(xiàn)程方法可以解決瓶頸并提供一種熟悉的做事方式。

輕量級(jí)線(xiàn)程

由于平臺(tái)線(xiàn)程的數(shù)量是無(wú)法在沒(méi)有更多硬件的情況下改變的,因此需要另一個(gè)抽象層,切斷可怕的 1:1 映射,它是首先造成瓶頸的原因。

輕量級(jí)線(xiàn)程不與特定的平臺(tái)線(xiàn)程綁定,也不會(huì)伴隨大量的預(yù)分配內(nèi)存。它們由運(yùn)行時(shí)而不是底層操作系統(tǒng)調(diào)度和管理。這就是為什么可以創(chuàng)建大量輕量級(jí)線(xiàn)程的原因。

這個(gè)概念并不新鮮,許多語(yǔ)言都采用某種形式的輕量級(jí)線(xiàn)程:

  • Go 語(yǔ)言中的 Goroutine
  • Erlang 進(jìn)程
  • Haskell 線(xiàn)程
  • 等等

Java最終于第21版中引入了自己的輕量級(jí)線(xiàn)程實(shí)現(xiàn):虛擬線(xiàn)程 (Virtual Threads)。

虛擬線(xiàn)程

虛擬線(xiàn)程是一種新的輕量級(jí)java.lang.Thread變體,是Project Loom的一部分,它不是由操作系統(tǒng)管理或調(diào)度的。相反,JVM負(fù)責(zé)調(diào)度。

當(dāng)然,任何實(shí)際的工作都必須在平臺(tái)線(xiàn)程中運(yùn)行,但是JVM使用所謂的“載體線(xiàn)程”(carrier threads) 來(lái)“攜帶”任何虛擬線(xiàn)程,以便在它們需要執(zhí)行時(shí)執(zhí)行這些線(xiàn)程。

圖片

JVM/操作系統(tǒng)線(xiàn)程調(diào)度器

所需的平臺(tái)線(xiàn)程在一個(gè) FIFO 工作竊取 ForkJoinPool 中進(jìn)行管理,該池默認(rèn)情況下使用所有可用的處理器,但可以通過(guò)調(diào)整系統(tǒng)屬性jdk.virtualThreadScheduler.parallelism來(lái)根據(jù)需求進(jìn)行修改。

ForkJoinPool與其他功能(例如并行流)使用的通用池之間的主要區(qū)別在于,通用池以LIFO模式運(yùn)行。

廉價(jià)且豐富的線(xiàn)程

擁有廉價(jià)且輕量級(jí)的線(xiàn)程,可以使用“每個(gè)請(qǐng)求一個(gè)線(xiàn)程”模型,而不必?fù)?dān)心實(shí)際需要多少個(gè)線(xiàn)程。如果你的代碼在虛擬線(xiàn)程中調(diào)用阻塞 I/O 操作,則運(yùn)行時(shí)會(huì)掛起虛擬線(xiàn)程,直到它可以稍后恢復(fù)。

這樣,硬件就可以被優(yōu)化到幾乎最佳的水平,從而實(shí)現(xiàn)高水平的并發(fā)性,因此也實(shí)現(xiàn)高吞吐量。

因?yàn)樗鼈兎浅A畠r(jià),所以虛擬線(xiàn)程不會(huì)被重用或需要池化。每個(gè)任務(wù)都由其自己的虛擬線(xiàn)程表示。

設(shè)置邊界

調(diào)度器負(fù)責(zé)管理載體線(xiàn)程,因此需要一定的邊界和分離,以確保可能的“無(wú)數(shù)”虛擬線(xiàn)程按照預(yù)期運(yùn)行。這是通過(guò)在載體線(xiàn)程及其可能攜帶的任何虛擬線(xiàn)程之間不保持線(xiàn)程關(guān)聯(lián)來(lái)實(shí)現(xiàn)的:

  • 虛擬線(xiàn)程無(wú)法訪問(wèn)載體,Thread.currentThread() 返回虛擬線(xiàn)程本身。
  • 堆棧跟蹤是分開(kāi)的,任何在虛擬線(xiàn)程中拋出的異常只包含其自己的堆棧幀。
  • 虛擬線(xiàn)程的線(xiàn)程局部變量對(duì)它的載體不可用,反之亦然。
  • 從代碼的角度來(lái)看,載體及其虛擬線(xiàn)程共享一個(gè)平臺(tái)線(xiàn)程是不可見(jiàn)的。

讓我們看看代碼

使用Virtual Threads最大的好處是,你不需要學(xué)習(xí)新的范例或復(fù)雜的API,就像使用異步編程一樣。相反,你可以像對(duì)待非虛擬線(xiàn)程一樣處理它們。

創(chuàng)建平臺(tái)線(xiàn)程

創(chuàng)建平臺(tái)線(xiàn)程很簡(jiǎn)單,就像使用 Runnable 創(chuàng)建一樣:

Runnable fn = () -> {
    // your code here
};

Thread thread = new Thread(fn).start();

隨著Project Loom簡(jiǎn)化了新的并發(fā)方法,它還提供了一種創(chuàng)建平臺(tái)支持線(xiàn)程的新方法:

Thread thread = Thread.ofPlatform().
                      .start(runnable);

實(shí)際上,現(xiàn)在還有一個(gè)完整的fluent API,因?yàn)閛fPlatform()會(huì)返回一個(gè)Thread.Builder.OfPlatform實(shí)例:

Thread thread = Thread.ofPlatform().
                      .daemon()
                      .name("my-custom-thread")
                      .unstarted(runnable);

但你肯定不是來(lái)學(xué)習(xí)創(chuàng)建“舊”線(xiàn)程的新方法的,我們想要一點(diǎn)新的東西。繼續(xù)看。

創(chuàng)建虛擬線(xiàn)程

對(duì)于虛擬線(xiàn)程,也有類(lèi)似的fluent API:

Runnable fn = () -> {
  // your code here
};

Thread thread = Thread.ofVirtual(fn)
                      .start();

除了構(gòu)建器方法之外,你還可以直接使用以下方式執(zhí)行Runnable:

Thread thread = Thread.startVirtualThread(() -> {
  // your code here
});

由于所有虛擬線(xiàn)程始終是守護(hù)線(xiàn)程,因此如果你想在主線(xiàn)程上等待,請(qǐng)不要忘記調(diào)用join()。

創(chuàng)建虛擬線(xiàn)程的另一種方法是使用 Executor:

var executorService = Executors.newVirtualThreadPerTaskExecutor();

executorService.submit(() -> {
  // your code here
});

小結(jié)

盡管Scoped Values (JEP 446) 和Structured Concurrency (JEP 453) 仍然是Java 21中的預(yù)覽功能,但Virtual Threads已經(jīng)成為一個(gè)成熟的、適用于生產(chǎn)環(huán)境的功能。

它們是Java并發(fā)的一種通用且強(qiáng)大的新方法,將對(duì)我們未來(lái)的程序產(chǎn)生重大影響。它們使用了熟悉的和可靠的“每個(gè)請(qǐng)求一個(gè)線(xiàn)程”方法,同時(shí)以最優(yōu)化的方式利用所有可用硬件,而不需要學(xué)習(xí)新的范例或復(fù)雜的API。


分享標(biāo)題:Java21的虛擬線(xiàn)程:高性能并發(fā)應(yīng)用的福音
網(wǎng)站URL:http://m.5511xx.com/article/cdieidj.html