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

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

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

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

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

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

        介紹

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

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

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

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

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

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

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

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

        摘要

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

        目標

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

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

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

        非目標

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

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

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

        動機

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

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

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

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

        兩種并發(fā) style

        thread-per-request style

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

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

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

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

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

        asynchronous style

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

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

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

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

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

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

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

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

        對比

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

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

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

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

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

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

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

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

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

        虛擬線程的意義

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

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

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

        說明

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

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

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

        虛擬線程 VS 平臺線程

        簡單示例

        開發(fā)人員可以選擇使用虛擬線程還是平臺線程。下面是一個創(chuàng)建大量虛擬線程的示例程序。該程序首先獲得一個 ExecutorService,它將為每個提交的任務(wù)創(chuàng)建一個新的虛擬線程。然后,它提交10000項任務(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ā)運行這些代碼。在幕后,JDK 在少數(shù)操作系統(tǒng)線程上運行代碼,可能只有一個線程。

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

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

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

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

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

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

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

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
        主站蜘蛛池模板: 精品国产一区二区三区AV性色| 精品国产成人在线| 亚洲综合国产精品| 人妻少妇精品中文字幕AV| 精品国产国产综合精品| 国产精品久久久久影院色 | 蜜臀久久99精品久久久久久小说| 国产99久久久国产精品~~牛 | 国产VA免费精品高清在线| 国产精品一区二区久久国产| 亚洲精品色婷婷在线影院| 国产三级精品三级在专区| 久久精品国产免费| 国产AV午夜精品一区二区三区| 亚洲国产精品无码久久久蜜芽 | 精品乱人伦一区二区三区| 久久综合久久自在自线精品自| 亚洲国产高清精品线久久| 99久久国产综合精品五月天喷水| 国内精品51视频在线观看| 国产精品igao视频网网址| 久久久国产精品亚洲一区| 亚洲色精品88色婷婷七月丁香| 欧美日韩精品一区二区三区不卡 | 99久久精品国产高清一区二区| 人妻熟妇乱又伦精品视频| 一本一本久久aa综合精品 | 大胸国产精品视频| 亚洲精品理论电影在线观看| 精品久久一区二区三区| 精品国产亚洲一区二区三区| 国产精品18久久久久久vr| 国产精品久线在线观看| HEYZO无码综合国产精品| 国产精品久久99| 麻豆精品成人免费国产片| 亚洲综合一区二区精品导航| 欧美黑人巨大精品| 91精品国产福利在线观看麻豆| 亚洲天堂久久精品| 99久久精品国产综合一区|