久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      Java知識點(diǎn)總結(jié)之JDK19虛擬線程

      本篇文章給大家?guī)砹岁P(guān)于java的相關(guān)知識,其中主要介紹了關(guān)于jdk19中虛擬線程的相關(guān)內(nèi)容,虛擬線程是具有和go語言的goroutines 和 Erlang 語言的進(jìn)程類似的實(shí)現(xiàn)方式,它們是用戶模式線程的一種形式,下面一起來看一下,希望對大家有幫助。

      Java知識點(diǎn)總結(jié)之JDK19虛擬線程

      程序員必備接口測試調(diào)試工具:立即使用
      Apipost = Postman + Swagger + Mock + Jmeter
      Api設(shè)計(jì)、調(diào)試、文檔、自動化測試工具
      后端、前端、測試,同時在線協(xié)作,內(nèi)容實(shí)時同步

      推薦學(xué)習(xí):《java視頻教程》

      介紹

      虛擬線程具有和 Go 語言的 goroutines 和 Erlang 語言的進(jìn)程類似的實(shí)現(xiàn)方式,它們是用戶模式(user-mode)線程的一種形式。

      在過去 Java 中常常使用線程池來進(jìn)行平臺線程的共享以提高對計(jì)算機(jī)硬件的使用率,但在這種異步風(fēng)格中,請求的每個階段可能在不同的線程上執(zhí)行,每個線程以交錯的方式運(yùn)行屬于不同請求的階段,與 Java 平臺的設(shè)計(jì)不協(xié)調(diào)從而導(dǎo)致:

      • 堆棧跟蹤不提供可用的上下文

      • 調(diào)試器不能單步執(zhí)行請求處理邏輯

      • 分析器不能將操作的成本與其調(diào)用方關(guān)聯(lián)。

      而虛擬線程既保持與平臺的設(shè)計(jì)兼容,同時又能最佳地利用硬件從而不影響可伸縮性。虛擬線程是由 JDK 而非操作系統(tǒng)提供的線程的輕量級實(shí)現(xiàn):

      • 虛擬線程是沒有綁定到特定操作系統(tǒng)線程的線程。

      • 平臺線程是以傳統(tǒng)方式實(shí)現(xiàn)的線程,作為圍繞操作系統(tǒng)線程的簡單包裝。

      摘要

      向 Java 平臺引入虛擬線程。虛擬線程是輕量級線程,它可以大大減少編寫、維護(hù)和觀察高吞吐量并發(fā)應(yīng)用程序的工作量。

      目標(biāo)

      • 允許以簡單的每個請求一個線程的方式編寫的服務(wù)器應(yīng)用程序以接近最佳的硬件利用率進(jìn)行擴(kuò)展。

      • 允許使用 java.lang.ThreadAPI 的現(xiàn)有代碼采用虛擬線程,并且只做最小的更改。

      • 使用現(xiàn)有的 JDK 工具可以方便地對虛擬線程進(jìn)行故障排除、調(diào)試和分析。

      非目標(biāo)

      • 移除線程的傳統(tǒng)實(shí)現(xiàn)或遷移現(xiàn)有應(yīng)用程序以使用虛擬線程并不是目標(biāo)。

      • 改變 Java 的基本并發(fā)模型。

      • 我們的目標(biāo)不是在 Java 語言或 Java 庫中提供新的資料平行結(jié)構(gòu)。StreamAPI 仍然是并行處理大型數(shù)據(jù)集的首選方法。

      動機(jī)

      近30年來,Java 開發(fā)人員一直依賴線程作為并發(fā)服務(wù)器應(yīng)用程序的構(gòu)件。每個方法中的每個語句都在一個線程中執(zhí)行,而且由于 Java 是多線程的,因此執(zhí)行的多個線程同時發(fā)生。

      線程是 Java 的并發(fā)單元: 一段順序代碼,與其他這樣的單元并發(fā)運(yùn)行,并且在很大程度上獨(dú)立于這些單元。

      每個線程都提供一個堆棧來存儲本地變量和協(xié)調(diào)方法調(diào)用,以及出錯時的上下文: 異常被同一個線程中的方法拋出和捕獲,因此開發(fā)人員可以使用線程的堆棧跟蹤來查找發(fā)生了什么。

      線程也是工具的一個核心概念: 調(diào)試器遍歷線程方法中的語句,分析器可視化多個線程的行為,以幫助理解它們的性能。

      兩種并發(fā) style

      thread-per-request style

      • 服務(wù)器應(yīng)用程序通常處理彼此獨(dú)立的并發(fā)用戶請求,因此應(yīng)用程序通過在整個請求持續(xù)期間為該請求分配一個線程來處理請求是有意義的。這種按請求執(zhí)行線程的 style 易于理解、易于編程、易于調(diào)試和配置,因?yàn)樗褂闷脚_的并發(fā)單元來表示應(yīng)用程序的并發(fā)單元。

      • 服務(wù)器應(yīng)用程序的可伸縮性受到利特爾定律(Little's Law)的支配,該定律關(guān)系到延遲、并發(fā)性和吞吐量: 對于給定的請求處理持續(xù)時間(延遲) ,應(yīng)用程序同時處理的請求數(shù)(并發(fā)性) 必須與到達(dá)速率(吞吐量) 成正比增長。

      • 例如,假設(shè)一個平均延遲為 50ms 的應(yīng)用程序通過并發(fā)處理 10 個請求實(shí)現(xiàn)每秒 200 個請求的吞吐量。為了使該應(yīng)用程序的吞吐量達(dá)到每秒 2000 個請求,它將需要同時處理 100 個請求。如果在請求持續(xù)期間每個請求都在一個線程中處理,那么為了讓應(yīng)用程序跟上,線程的數(shù)量必須隨著吞吐量的增長而增長。

      • 不幸的是,可用線程的數(shù)量是有限的,因?yàn)?JDK 將線程實(shí)現(xiàn)為操作系統(tǒng)(OS)線程的包裝器。操作系統(tǒng)線程代價高昂,因此我們不能擁有太多線程,這使得實(shí)現(xiàn)不適合每個請求一個線程的 style 。

      • 如果每個請求在其持續(xù)時間內(nèi)消耗一個線程,從而消耗一個 OS 線程,那么線程的數(shù)量通常會在其他資源(如 CPU 或網(wǎng)絡(luò)連接)耗盡之前很久成為限制因素。JDK 當(dāng)前的線程實(shí)現(xiàn)將應(yīng)用程序的吞吐量限制在遠(yuǎn)低于硬件所能支持的水平。即使在線程池中也會發(fā)生這種情況,因?yàn)槌赜兄诒苊鈫有戮€程的高成本,但不會增加線程的總數(shù)。

      asynchronous style

      一些希望充分利用硬件的開發(fā)人員已經(jīng)放棄了每個請求一個線程(thread-per-request) 的 style ,轉(zhuǎn)而采用線程共享(thread-sharing ) 的 style 。

      請求處理代碼不是從頭到尾處理一個線程上的請求,而是在等待 I/O 操作完成時將其線程返回到一個池中,以便該線程能夠處理其他請求。這種細(xì)粒度的線程共享(其中代碼只在執(zhí)行計(jì)算時保留一個線程,而不是在等待 I/O 時保留該線程)允許大量并發(fā)操作,而不需要消耗大量線程。

      雖然它消除了操作系統(tǒng)線程的稀缺性對吞吐量的限制,但代價很高: 它需要一種所謂的異步編程 style ,采用一組獨(dú)立的 I/O 方法,這些方法不等待 I/O 操作完成,而是在以后將其完成信號發(fā)送給回調(diào)。如果沒有專門的線程,開發(fā)人員必須將請求處理邏輯分解成小的階段,通常以 lambda 表達(dá)式的形式編寫,然后將它們組合成帶有 API 的順序管道(例如,參見 CompletableFuture,或者所謂的“反應(yīng)性”框架)。因此,它們放棄了語言的基本順序組合運(yùn)算符,如循環(huán)和 try/catch 塊。

      在異步樣式中,請求的每個階段可能在不同的線程上執(zhí)行,每個線程以交錯的方式運(yùn)行屬于不同請求的階段。這對于理解程序行為有著深刻的含義:

      • 堆棧跟蹤不提供可用的上下文

      • 調(diào)試器不能單步執(zhí)行請求處理邏輯

      • 分析器不能將操作的成本與其調(diào)用方關(guān)聯(lián)。

      當(dāng)使用 Java 的流 API 在短管道中處理數(shù)據(jù)時,組合 lambda 表達(dá)式是可管理的,但是當(dāng)應(yīng)用程序中的所有請求處理代碼都必須以這種方式編寫時,就有問題了。這種編程 style 與 Java 平臺不一致,因?yàn)閼?yīng)用程序的并發(fā)單元(異步管道)不再是平臺的并發(fā)單元。

      對比

      Java知識點(diǎn)總結(jié)之JDK19虛擬線程

      使用虛擬線程保留thread-per-request style

      為了使應(yīng)用程序能夠在與平臺保持和諧的同時進(jìn)行擴(kuò)展,我們應(yīng)該通過更有效地實(shí)現(xiàn)線程來努力保持每個請求一個線程的 style ,以便它們能夠更加豐富。

      操作系統(tǒng)無法更有效地實(shí)現(xiàn) OS 線程,因?yàn)椴煌恼Z言和運(yùn)行時以不同的方式使用線程堆棧。然而,Java 運(yùn)行時實(shí)現(xiàn) Java 線程的方式可以切斷它們與操作系統(tǒng)線程之間的一一對應(yīng)關(guān)系。正如操作系統(tǒng)通過將大量虛擬地址空間映射到有限數(shù)量的物理 RAM 而給人一種內(nèi)存充足的錯覺一樣,Java 運(yùn)行時也可以通過將大量虛擬線程映射到少量操作系統(tǒng)線程而給人一種線程充足的錯覺。

      • 虛擬線程是沒有綁定到特定操作系統(tǒng)線程的線程。

      • 平臺線程是以傳統(tǒng)方式實(shí)現(xiàn)的線程,作為圍繞操作系統(tǒng)線程的簡單包裝。

      thread-per-request 樣式的應(yīng)用程序代碼可以在整個請求期間在虛擬線程中運(yùn)行,但是虛擬線程只在 CPU 上執(zhí)行計(jì)算時使用操作系統(tǒng)線程。其結(jié)果是與異步樣式相同的可伸縮性,除了它是透明實(shí)現(xiàn)的:

      當(dāng)在虛擬線程中運(yùn)行的代碼調(diào)用 Java.* API 中的阻塞 I/O 操作時,運(yùn)行時執(zhí)行一個非阻塞操作系統(tǒng)調(diào)用,并自動掛起虛擬線程,直到稍后可以恢復(fù)。

      對于 Java 開發(fā)人員來說,虛擬線程是創(chuàng)建成本低廉、數(shù)量幾乎無限多的線程。硬件利用率接近最佳,允許高水平的并發(fā)性,從而提高吞吐量,而應(yīng)用程序仍然與 Java 平臺及其工具的多線程設(shè)計(jì)保持協(xié)調(diào)。

      虛擬線程的意義

      虛擬線程是廉價和豐富的,因此永遠(yuǎn)不應(yīng)該被共享(即使用線程池) : 應(yīng)該為每個應(yīng)用程序任務(wù)創(chuàng)建一個新的虛擬線程。

      因此,大多數(shù)虛擬線程的壽命都很短,并且具有淺層調(diào)用堆棧,執(zhí)行的操作只有單個 HTTP 客戶機(jī)調(diào)用或單個 JDBC 查詢那么少。相比之下,平臺線程是重量級和昂貴的,因此經(jīng)常必須共享。它們往往是長期存在的,具有深度調(diào)用堆棧,并且在許多任務(wù)之間共享。

      總之,虛擬線程保留了可靠的 thread-per-request style ,這種 style 與 Java 平臺的設(shè)計(jì)相協(xié)調(diào),同時又能最佳地利用硬件。使用虛擬線程并不需要學(xué)習(xí)新的概念,盡管它可能需要為應(yīng)對當(dāng)今線程的高成本而養(yǎng)成的忘卻習(xí)慣。虛擬線程不僅可以幫助應(yīng)用程序開發(fā)人員ーー它們還可以幫助框架設(shè)計(jì)人員提供易于使用的 API,這些 API 與平臺的設(shè)計(jì)兼容,同時又不影響可伸縮性。

      說明

      如今,java.lang 的每一個實(shí)例。JDK 中的線程是一個平臺線程。平臺線程在底層操作系統(tǒng)線程上運(yùn)行 Java 代碼,并在代碼的整個生命周期中捕獲操作系統(tǒng)線程。平臺線程的數(shù)量僅限于操作系統(tǒng)線程的數(shù)量。

      虛擬線程是 java.lang 的一個實(shí)例。在基礎(chǔ)操作系統(tǒng)線程上運(yùn)行 Java 代碼,但在代碼的整個生命周期中不捕獲該操作系統(tǒng)線程的線程。這意味著許多虛擬線程可以在同一個 OS 線程上運(yùn)行它們的 Java 代碼,從而有效地共享它們。平臺線程壟斷了一個珍貴的操作系統(tǒng)線程,而虛擬線程卻沒有。虛擬線程的數(shù)量可能比操作系統(tǒng)線程的數(shù)量大得多。

      虛擬線程是由 JDK 而非操作系統(tǒng)提供的線程的輕量級實(shí)現(xiàn)。它們是用戶模式(user-mode)線程的一種形式,已經(jīng)在其他多線程語言中取得了成功(例如,Go 中的 goroutines 和 Erlang 的進(jìn)程)。在 Java 的早期版本中,用戶模式線程甚至以所謂的“綠線程”為特色,當(dāng)時 OS 線程還不成熟和普及。然而,Java 的綠色線程都共享一個 OS 線程(M: 1調(diào)度) ,并最終被平臺線程超越,實(shí)現(xiàn)為 OS 線程的包裝器(1:1調(diào)度)。虛擬線程采用 M: N 調(diào)度,其中大量(M)虛擬線程被調(diào)度在較少(N)操作系統(tǒng)線程上運(yùn)行。

      虛擬線程 VS 平臺線程

      簡單示例

      開發(fā)人員可以選擇使用虛擬線程還是平臺線程。下面是一個創(chuàng)建大量虛擬線程的示例程序。該程序首先獲得一個 ExecutorService,它將為每個提交的任務(wù)創(chuàng)建一個新的虛擬線程。然后,它提交10000項(xiàng)任務(wù),等待所有任務(wù)完成:

      try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {     IntStream.range(0, 10000).forEach(i -> {         executor.submit(() -> {             Thread.sleep(Duration.ofSeconds(1));             return i;         });     }); }  // executor.close() is called implicitly, and waits
      登錄后復(fù)制

      本例中的任務(wù)是簡單的代碼(休眠一秒鐘) ,現(xiàn)代硬件可以輕松支持10,000個虛擬線程并發(fā)運(yùn)行這些代碼。在幕后,JDK 在少數(shù)操作系統(tǒng)線程上運(yùn)行代碼,可能只有一個線程。

      如果這個程序使用 ExecutorService 為每個任務(wù)創(chuàng)建一個新的平臺線程,比如 Executors.newCachedThreadPool () ,那么情況就會大不相同。ExecutorService 將嘗試創(chuàng)建10,000個平臺線程,從而創(chuàng)建10,000個 OS 線程,程序可能會崩潰,這取決于計(jì)算機(jī)和操作系統(tǒng)。

      相反,如果程序使用從池中獲取平臺線程的 ExecutorService (例如 Executors.newFixedThreadPool (200)) ,情況也不會好到哪里去。ExecutorService 將創(chuàng)建200個平臺線程,由所有10,000個任務(wù)共享,因此許多任務(wù)將按順序運(yùn)行,而不是并發(fā)運(yùn)行,而且程序?qū)⑿枰荛L時間才能完成。對于這個程序,一個有200個平臺線程的池只能達(dá)到每秒200個任務(wù)的吞吐量,而虛擬線程達(dá)到每秒10,000個任務(wù)的吞吐量(在充分預(yù)熱之后)。此外,如果示例程序中的10000被更改為1000000,那么該程序?qū)⑻峤?,000,000個任務(wù),創(chuàng)建1,000,000個并發(fā)運(yùn)行的虛擬線程,并且(在足夠的預(yù)熱之后)實(shí)現(xiàn)大約1,000,000任務(wù)/秒的吞吐量。

      如果這個程序中的任務(wù)執(zhí)行一秒鐘的計(jì)算(例如,對一個巨大的數(shù)組進(jìn)行排序)而不僅僅是休眠,那么增加超出處理器核心數(shù)量的線程數(shù)量將無濟(jì)于事,無論它們是虛擬線程還是平臺線程。

      虛擬線程并不是更快的線程ーー它們運(yùn)行代碼的速度并不比平臺線程快。它們的存在是為了提供規(guī)模(更高的吞吐量) ,而不是速度(更低的延遲) 。它們的數(shù)量可能比平臺線程多得多,因此根據(jù) Little’s Law,它們能夠?qū)崿F(xiàn)更高吞吐量所需的更高并發(fā)性。

      換句話說,虛擬線程可以顯著提高應(yīng)用程序的吞吐量,在如下情況時:

      • 并發(fā)任務(wù)的數(shù)量很多(超過幾千個)

      • 工作負(fù)載不受 CPU 限制,因?yàn)樵谶@種情況下,比處理器核心擁有

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號