站長資訊網
最全最豐富的資訊網站

Java知識點總結之JDK19虛擬線程

本篇文章給大家帶來了關于java的相關知識,其中主要介紹了關于jdk19中虛擬線程的相關內容,虛擬線程是具有和go語言的goroutines 和 Erlang 語言的進程類似的實現方式,它們是用戶模式線程的一種形式,下面一起來看一下,希望對大家有幫助。

Java知識點總結之JDK19虛擬線程

程序員必備接口測試調試工具:立即使用
Apipost = Postman + Swagger + Mock + Jmeter
Api設計、調試、文檔、自動化測試工具
后端、前端、測試,同時在線協作,內容實時同步

推薦學習:《java視頻教程》

介紹

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

在過去 Java 中常常使用線程池來進行平臺線程的共享以提高對計算機硬件的使用率,但在這種異步風格中,請求的每個階段可能在不同的線程上執行,每個線程以交錯的方式運行屬于不同請求的階段,與 Java 平臺的設計不協調從而導致:

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

  • 調試器不能單步執行請求處理邏輯

  • 分析器不能將操作的成本與其調用方關聯。

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

  • 虛擬線程是沒有綁定到特定操作系統線程的線程。

  • 平臺線程是以傳統方式實現的線程,作為圍繞操作系統線程的簡單包裝。

摘要

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

目標

  • 允許以簡單的每個請求一個線程的方式編寫的服務器應用程序以接近最佳的硬件利用率進行擴展。

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

  • 使用現有的 JDK 工具可以方便地對虛擬線程進行故障排除、調試和分析。

非目標

  • 移除線程的傳統實現或遷移現有應用程序以使用虛擬線程并不是目標。

  • 改變 Java 的基本并發模型。

  • 我們的目標不是在 Java 語言或 Java 庫中提供新的資料平行結構。StreamAPI 仍然是并行處理大型數據集的首選方法。

動機

近30年來,Java 開發人員一直依賴線程作為并發服務器應用程序的構件。每個方法中的每個語句都在一個線程中執行,而且由于 Java 是多線程的,因此執行的多個線程同時發生。

線程是 Java 的并發單元: 一段順序代碼,與其他這樣的單元并發運行,并且在很大程度上獨立于這些單元。

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

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

兩種并發 style

thread-per-request style

  • 服務器應用程序通常處理彼此獨立的并發用戶請求,因此應用程序通過在整個請求持續期間為該請求分配一個線程來處理請求是有意義的。這種按請求執行線程的 style 易于理解、易于編程、易于調試和配置,因為它使用平臺的并發單元來表示應用程序的并發單元。

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

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

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

  • 如果每個請求在其持續時間內消耗一個線程,從而消耗一個 OS 線程,那么線程的數量通常會在其他資源(如 CPU 或網絡連接)耗盡之前很久成為限制因素。JDK 當前的線程實現將應用程序的吞吐量限制在遠低于硬件所能支持的水平。即使在線程池中也會發生這種情況,因為池有助于避免啟動新線程的高成本,但不會增加線程的總數。

asynchronous style

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

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

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

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

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

  • 調試器不能單步執行請求處理邏輯

  • 分析器不能將操作的成本與其調用方關聯。

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

對比

Java知識點總結之JDK19虛擬線程

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

為了使應用程序能夠在與平臺保持和諧的同時進行擴展,我們應該通過更有效地實現線程來努力保持每個請求一個線程的 style ,以便它們能夠更加豐富。

操作系統無法更有效地實現 OS 線程,因為不同的語言和運行時以不同的方式使用線程堆棧。然而,Java 運行時實現 Java 線程的方式可以切斷它們與操作系統線程之間的一一對應關系。正如操作系統通過將大量虛擬地址空間映射到有限數量的物理 RAM 而給人一種內存充足的錯覺一樣,Java 運行時也可以通過將大量虛擬線程映射到少量操作系統線程而給人一種線程充足的錯覺。

  • 虛擬線程是沒有綁定到特定操作系統線程的線程。

  • 平臺線程是以傳統方式實現的線程,作為圍繞操作系統線程的簡單包裝。

thread-per-request 樣式的應用程序代碼可以在整個請求期間在虛擬線程中運行,但是虛擬線程只在 CPU 上執行計算時使用操作系統線程。其結果是與異步樣式相同的可伸縮性,除了它是透明實現的:

當在虛擬線程中運行的代碼調用 Java.* API 中的阻塞 I/O 操作時,運行時執行一個非阻塞操作系統調用,并自動掛起虛擬線程,直到稍后可以恢復。

對于 Java 開發人員來說,虛擬線程是創建成本低廉、數量幾乎無限多的線程。硬件利用率接近最佳,允許高水平的并發性,從而提高吞吐量,而應用程序仍然與 Java 平臺及其工具的多線程設計保持協調。

虛擬線程的意義

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

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

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

說明

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

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

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

虛擬線程 VS 平臺線程

簡單示例

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

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
登錄后復制

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

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

相反,如果程序使用從池中獲取平臺線程的 ExecutorService (例如 Executors.newFixedThreadPool (200)) ,情況也不會好到哪里去。ExecutorService 將創建200個平臺線程,由所有10,000個任務共享,因此許多任務將按順序運行,而不是并發運行,而且程序將需要很長時間才能完成。對于這個程序,一個有200個平臺線程的池只能達到每秒200個任務的吞吐量,而虛擬線程達到每秒10,000個任務的吞吐量(在充分預熱之后)。此外,如果示例程序中的10000被更改為1000000,那么該程序將提交1,000,000個任務,創建1,000,000個并發運行的虛擬線程,并且(在足夠的預熱之后)實現大約1,000,000任務/秒的吞吐量。

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

虛擬線程并不是更快的線程ーー它們運行代碼的速度并不比平臺線程快。它們的存在是為了提供規模(更高的吞吐量) ,而不是速度(更低的延遲) 。它們的數量可能比平臺線程多得多,因此根據 Little’s Law,它們能夠實現更高吞吐量所需的更高并發性。

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

  • 并發任務的數量很多(超過幾千個)

  • 工作負載不受 CPU 限制,因為在這種情況下,比處理器核心擁有

贊(0)
分享到: 更多 (0)
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
日韩中文字幕免费视频| 自拍偷在线精品自拍偷无码专区| 午夜精品久久久内射近拍高清| 日本精品中文字幕| 男人扒开女人下添高潮日韩视频 | 182tv午夜精品视频在线播放| 日本精品3d动漫一区二区| 亚洲国产成人一区二区精品区| 国产精品∧v在线观看| 久久精品国产亚洲香蕉| 精品特级一级毛片免费观看| 97久久精品无码一区二区| 亚洲精品无码MV在线观看| 麻豆国产96在线日韩麻豆| 九九精品久久久久久噜噜| 国产精品免费AV片在线观看| 日韩国产成人资源精品视频| 精品丰满人妻无套内射| 少妇人妻偷人精品免费视频| 国产成人精品久久一区二区三区av | 日韩免费观看视频| 亚洲av永久无码精品网址| 久久国产精品99久久久久久牛牛| 国产女精品视频在ktv| 精品国产福利一区二区| 国产亚洲精品国产| 日韩精品一区二区三区老鸦窝| 久久久精品国产免大香伊 | 在线观看日韩精品| 精品综合久久久久久88小说| 日韩三级草久国产| 亚洲精品456人成在线| 亚洲天堂久久精品| 99re热这里只有精品视频中文字幕 | 99精品视频观看| 91国在线啪精品一区| 日韩成人无码一区二区三区| 亚洲精品成a人在线观看☆| 久热这里只有精品12| 91精品国产综合久久久久久| 2021日韩麻豆|