日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

提升系統(tǒng)吞吐量,詳解JDK21虛擬線程,炸裂

來源: 責(zé)編: 時間:2024-06-06 17:36:22 153觀看
導(dǎo)讀環(huán)境:JDK211. 虛擬線程簡介虛擬線程是輕量級的線程,可以減少編寫、維護和調(diào)試高吞吐量并發(fā)應(yīng)用程序的工作量。線程是可以調(diào)度的最小處理單元。它與其他類似單元并發(fā)運行,而且在很大程度上是獨立運行的。它是java.lang.Th

環(huán)境:JDK21kCa28資訊網(wǎng)——每日最新資訊28at.com

1. 虛擬線程簡介

虛擬線程是輕量級的線程,可以減少編寫、維護和調(diào)試高吞吐量并發(fā)應(yīng)用程序的工作量。線程是可以調(diào)度的最小處理單元。它與其他類似單元并發(fā)運行,而且在很大程度上是獨立運行的。它是java.lang.Thread的一個實例。線程有兩種,平臺線程和虛擬線程。kCa28資訊網(wǎng)——每日最新資訊28at.com

2. 什么是平臺線程

平臺線程被實現(xiàn)為操作系統(tǒng)(OS)線程的薄包裝器。平臺線程在其底層操作系統(tǒng)線程上運行Java代碼,平臺線程在平臺線程的整個生命周期中捕獲其操作系統(tǒng)線程。因此,可用平臺線程的數(shù)量受限于操作系統(tǒng)線程的數(shù)量。kCa28資訊網(wǎng)——每日最新資訊28at.com

平臺線程通常有一個比較大的線程堆棧和由操作系統(tǒng)維護的其他資源。它們適用于運行所有類型的任務(wù),但可能是有限的資源。kCa28資訊網(wǎng)——每日最新資訊28at.com

3. 什么是虛擬線程

與平臺線程一樣,虛擬線程也是java.lang.thread的一個實例。然而,虛擬線程并沒有綁定到特定的操作系統(tǒng)線程。虛擬線程仍然在操作系統(tǒng)線程上運行代碼。但是,當(dāng)虛擬線程中運行的代碼調(diào)用阻塞I/O操作時,Java運行時會掛起虛擬線程,直到可以恢復(fù)為止。與掛起的虛擬線程相關(guān)聯(lián)的OS線程現(xiàn)在可以自由地執(zhí)行其他虛擬線程的操作。kCa28資訊網(wǎng)——每日最新資訊28at.com

虛擬線程的實現(xiàn)方式與虛擬內(nèi)存類似。為了模擬大量內(nèi)存,操作系統(tǒng)將大量虛擬地址空間映射到有限的RAM。同樣,為了模擬大量線程,Java運行時將大量虛擬線程映射到少量操作系統(tǒng)線程。kCa28資訊網(wǎng)——每日最新資訊28at.com

與平臺線程不同,虛擬線程通常有一個淺調(diào)用堆棧,只執(zhí)行一個HTTP客戶端調(diào)用或一個JDBC查詢。盡管虛擬線程支持線程本地變量和可繼承的線程本地變量,但應(yīng)該仔細考慮使用它們,因為單個JVM可能支持數(shù)百萬個虛擬線程。kCa28資訊網(wǎng)——每日最新資訊28at.com

虛擬線程適用于運行大部分時間被阻塞的任務(wù),這些任務(wù)通常等待I/O操作完成。然而,它們并不適用于長時間運行的CPU密集型操作。kCa28資訊網(wǎng)——每日最新資訊28at.com

4. 為什么使用虛擬線程

在高吞吐量并發(fā)應(yīng)用程序中使用虛擬線程,尤其是那些由大量并發(fā)任務(wù)組成、花費大量時間等待的應(yīng)用程序。服務(wù)器應(yīng)用程序是高吞吐量應(yīng)用程序的示例,因為它們通常處理許多執(zhí)行阻塞I/O操作(如獲取資源)的客戶端請求。kCa28資訊網(wǎng)——每日最新資訊28at.com

虛擬線程不是更快的線程;它們運行代碼的速度并不比平臺線程快。它們的存在是為了提供規(guī)模(更高的吞吐量),而不是速度(更低的延遲)。kCa28資訊網(wǎng)——每日最新資訊28at.com

5. 創(chuàng)建虛擬線程

Thread和Thread.Builder APIs提供了創(chuàng)建平臺線程和虛擬線程的方法。java.util.concurrent.Executors類還定義了創(chuàng)建ExecutorService的方法,該方法為每個任務(wù)啟動一個新的虛擬線程。kCa28資訊網(wǎng)——每日最新資訊28at.com

5.1 Thread & Thread.Builder創(chuàng)建虛擬線程

調(diào)用Thread.ofVirtual()方法創(chuàng)建一個Thread.Builder實例,用于創(chuàng)建虛擬線程。如下示例:kCa28資訊網(wǎng)——每日最新資訊28at.com

Thread t= Thread.ofVirtual().start(() -> System.out.println("Hello")) ;t.join() ;

Thread.Builder接口允許創(chuàng)建具有公共線程屬性(如線程名稱)的線程。Thread.Builder.OfPlatform子接口創(chuàng)建平臺線程,而Thread.Builder.OfVirtual創(chuàng)建虛擬線程。kCa28資訊網(wǎng)——每日最新資訊28at.com

下面的示例使用Thread.Builder接口創(chuàng)建一個名為T-VM的虛擬線程,如下示例:kCa28資訊網(wǎng)——每日最新資訊28at.com

Thread.Builder builder = Thread.ofVirtual().name("T-VM") ;Runnable task = () -> {  System.out.println("執(zhí)行任務(wù)") ;} ;Thread t = builder.start(task) ;System.err.printf("線程名稱: %s%n", t.getName()) ;t.join() ;

輸出結(jié)果:kCa28資訊網(wǎng)——每日最新資訊28at.com

執(zhí)行任務(wù)線程名稱T-VM

下面的示例創(chuàng)建并啟動兩個具有Thread.Builder的虛擬線程:kCa28資訊網(wǎng)——每日最新資訊28at.com

Thread.Builder builder = Thread.ofVirtual().name("vm - worker - ", 0);Runnable task = () -> {  System.out.printf("線程ID: %d%n", Thread.currentThread().threadId());} ;// 線程 "vm - worker - 0"Thread t1 = builder.start(task) ;   t1.join();System.out.println(t1.getName() + " terminated") ;// 線程 "vm - worker - 1"Thread t2 = builder.start(task) ;   t2.join() ;  System.out.println(t2.getName() + " terminated") ;

輸出結(jié)果:kCa28資訊網(wǎng)——每日最新資訊28at.com

線程ID: 21vm - worker - 0 terminated線程ID: 24vm - worker - 1 terminated

以上是通過Thread.Builder創(chuàng)建虛擬線程的簡單示例。kCa28資訊網(wǎng)——每日最新資訊28at.com

5.2 Executors創(chuàng)建虛擬線程

Executors允許將線程管理和創(chuàng)建與應(yīng)用程序的其余部分分離。kCa28資訊網(wǎng)——每日最新資訊28at.com

ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor() ;// submit Runnable任務(wù)Future<?> future = executor.submit(() -> System.out.println("Running thread")) ;future.get() ;System.out.println("Task completed") ;

上面示例每當(dāng)調(diào)用ExecutorService.submit(Runnable)時,都會創(chuàng)建一個新的虛擬線程并開始運行該任務(wù)。kCa28資訊網(wǎng)——每日最新資訊28at.com

6. 虛擬線程調(diào)度

操作系統(tǒng)在平臺線程運行時進行調(diào)度。然而,Java運行時會在虛擬線程運行時進行調(diào)度。當(dāng)Java運行時調(diào)度虛擬線程時,它將虛擬線程分配或掛載到平臺線程上,然后操作系統(tǒng)像往常一樣調(diào)度該平臺線程。這個平臺線程稱為載體(carrier)。運行一些代碼后,虛擬線程可以從它的載體卸載。這通常發(fā)生在虛擬線程執(zhí)行阻塞I/O操作時。當(dāng)一個虛擬線程從其宿主中卸載后,宿主就處于空閑狀態(tài),這意味著Java運行時調(diào)度器可以在其上分配另一個虛擬線程。kCa28資訊網(wǎng)——每日最新資訊28at.com

虛擬線程被綁定到其宿主(平臺線程)時,在阻塞操作期間無法將其卸載。虛擬線程在以下情況下會被綁定:kCa28資訊網(wǎng)——每日最新資訊28at.com

  • 虛擬線程在同步塊或方法內(nèi)運行代碼
  • 虛擬線程運行本機方法或外部函數(shù)

7. 虛擬線程應(yīng)用指南

虛擬線程是由Java運行時而不是操作系統(tǒng)實現(xiàn)的Java線程。虛擬線程和傳統(tǒng)線程(平臺線程)的主要區(qū)別在于,可以很容易地在同一個Java進程中運行大量甚至數(shù)百萬個活動的虛擬線程。正是它們的數(shù)量賦予了虛擬線程強大的能力,通過允許服務(wù)器并發(fā)處理更多請求,它們可以更高效地運行以"thread-per-request"風(fēng)格編寫的服務(wù)器應(yīng)用程序,從而提高吞吐量,減少硬件浪費。kCa28資訊網(wǎng)——每日最新資訊28at.com

虛擬線程可以顯著提高以thread-per-request風(fēng)格編寫的服務(wù)器的吞吐量,而不是延遲。在這種風(fēng)格中,服務(wù)器在整個持續(xù)時間內(nèi)使用一個線程來處理每個傳入的請求。它至少占用一個線程,因為在處理單個請求時,你可能希望使用更多線程并發(fā)地執(zhí)行某些任務(wù)。kCa28資訊網(wǎng)——每日最新資訊28at.com

阻塞平臺線程的代價是昂貴的,因為它會占用線程——這是一種相對稀缺的資源——而線程并沒有做很多有意義的工作。因為虛擬線程可能很多,所以阻塞它們是廉價的,也是值得鼓勵的。因此,應(yīng)該使用簡單的同步風(fēng)格并使用阻塞I/O API編寫代碼。kCa28資訊網(wǎng)——每日最新資訊28at.com

如下代碼以非阻塞異步風(fēng)格編寫,不會從虛擬線程中獲得太多好處。kCa28資訊網(wǎng)——每日最新資訊28at.com

HttpClient client = ... ;Executor pool = Executors.newVirtualThreadPerTaskExecutor() ;CompletableFuture.supplyAsync(() -> {  HttpRequest request = HttpRequest.newBuilder(URI.create("http://localhost:8088/users/info")).build() ;  BodyHandler<String> bodyHandler = ... ;  try {    return client.send(request , bodyHandler) ;  }}, pool).thenCompose(url -> getBodyAsync(url, HttpResponse.BodyHandlers.ofString())).thenApply(info::findImage).thenAccept(this::process).exceptionally(t -> { t.printStackTrace(); return null; });

相反,以下代碼以同步風(fēng)格編寫,并使用簡單的阻塞IO,將受益匪淺:kCa28資訊網(wǎng)——每日最新資訊28at.com

try {   String page = getBody(info.getUrl(), HttpResponse.BodyHandlers.ofString());   String imageUrl = info.findImage(page);   byte[] data = getBody(imageUrl, HttpResponse.BodyHandlers.ofByteArray());      info.setImageData(data);   process(info);}

8. 不要池化虛擬線程

關(guān)于虛擬線程最難理解的是,雖然它們與平臺線程具有相同的行為,但它們不應(yīng)該表示相同的程序概念。kCa28資訊網(wǎng)——每日最新資訊28at.com

平臺線程很少,因此是一種寶貴的資源。寶貴的資源需要管理,管理平臺線程的最常見方法是使用線程池。接下來你需要回答的問題是,線程池中應(yīng)該有多少個線程?kCa28資訊網(wǎng)——每日最新資訊28at.com

但是虛擬線程是很多的,因此每個線程不應(yīng)該代表某種共享的、池化的資源,而應(yīng)該代表一個任務(wù)。kCa28資訊網(wǎng)——每日最新資訊28at.com

將n個平臺線程轉(zhuǎn)換為n個虛擬線程幾乎沒有好處;相反,需要轉(zhuǎn)換的是任務(wù)。kCa28資訊網(wǎng)——每日最新資訊28at.com

為了將每個應(yīng)用任務(wù)表示為一個線程,不要像下面的例子那樣使用共享線程池:kCa28資訊網(wǎng)——每日最新資訊28at.com

Future<ResultA> f1 = sharedThreadPoolExecutor.submit(task1);Future<ResultB> f2 = sharedThreadPoolExecutor.submit(task2);// ... use futures

相反,使用虛擬線程kCa28資訊網(wǎng)——每日最新資訊28at.com

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {   Future<ResultA> f1 = executor.submit(task1);   Future<ResultB> f2 = executor.submit(task2);   // ... use futures}

上面的代碼仍然使用ExecutorService,但從Executors.newVirtualThreadPerTaskExecutor()返回的代碼沒有使用線程池。相反,它為每個提交的任務(wù)創(chuàng)建一個新的虛擬線程。kCa28資訊網(wǎng)——每日最新資訊28at.com

此外,ExecutorService本身是輕量級的,我們可以像創(chuàng)建任何簡單對象一樣創(chuàng)建一個新的對象。這使得我們可以依賴新添加的ExecutorService#close方法和try-with-resources構(gòu)造。close方法會在try塊結(jié)束時隱式調(diào)用,它會自動等待所有提交給ExecutorService的任務(wù)(即由ExecutorService生成的所有虛擬線程)結(jié)束。kCa28資訊網(wǎng)——每日最新資訊28at.com

對于扇出場景來說,這是一個特別有用的模式,在這種場景中,同時執(zhí)行多個對不同服務(wù)調(diào)用,如下面的示例所示:kCa28資訊網(wǎng)——每日最新資訊28at.com

void handle() throws Exception {  URL url1 = URI.create("http://www.pack.com").toURL() ;  URL url2 = URI.create("http://www.akf.com").toURL() ;  try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {    var future1 = executor.submit(() -> fetchURL(url1));    var future2 = executor.submit(() -> fetchURL(url2));    System.out.printf("result1: %s, result2: %s%n", future1.get(),future2.get()) ;  }}String fetchURL(URL url) throws IOException {  try (var in = url.openStream()) {    return new String(in.readAllBytes(), StandardCharsets.UTF_8);  }}

你應(yīng)該創(chuàng)建一個新的虛擬線程,如上所示,即使是小的、短期的并發(fā)任務(wù)。kCa28資訊網(wǎng)——每日最新資訊28at.com

9. 避免長時間頻繁的Pinning

當(dāng)前實現(xiàn)虛擬線程的一個限制是,在同步的塊或方法內(nèi)部執(zhí)行阻塞操作會導(dǎo)致JDK的虛擬線程調(diào)度器阻塞一個操作系統(tǒng)線程,而在同步的塊或方法外部執(zhí)行阻塞操作則不會。這種情況稱為“Pinning”。如果阻塞操作持續(xù)時間長且頻繁,Pinning可能會對服務(wù)器的吞吐量產(chǎn)生負面影響。保護短期的操作,例如內(nèi)存操作,或者使用同步塊或方法的不頻繁操作,應(yīng)該不會有任何負面影響。kCa28資訊網(wǎng)——每日最新資訊28at.com

對于長時間又頻繁的地方應(yīng)該使用ReentrantLock替換synchronized 。kCa28資訊網(wǎng)——每日最新資訊28at.com

synchronized(lockObj) {  frequentIO() ;}// 替換為lock.lock();try {  frequentIO() ;} finally {  lock.unlock() ;}


kCa28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-92454-0.html提升系統(tǒng)吞吐量,詳解JDK21虛擬線程,炸裂

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 強勢問鼎!強力巨彩斬獲 2023 年 LED 顯示屏銷量第一!

下一篇: 代碼中預(yù)編譯常見指令用法

標(biāo)簽:
  • 熱門焦點
  • MIX Fold3包裝盒泄露 新機本月登場

    小米的全新折疊屏旗艦MIX Fold3將于本月發(fā)布,近日該機的真機包裝盒在網(wǎng)上泄露。從圖上來看,新的MIX Fold3包裝盒在外觀設(shè)計方面延續(xù)了之前的方案,變化不大,這也是目前小米旗艦
  • 俄羅斯:將審查iPhone等外國公司設(shè)備 保數(shù)據(jù)安全

    iPhone和特斯拉都屬于在各自領(lǐng)域領(lǐng)頭羊的品牌,推出的產(chǎn)品也也都是數(shù)一數(shù)二的,但對于一些國家而言,它們的產(chǎn)品可靠性和安全性還是在限制范圍內(nèi)。近日,俄羅斯聯(lián)邦通信、信息技術(shù)
  • 把LangChain跑起來的三個方法

    使用LangChain開發(fā)LLM應(yīng)用時,需要機器進行GLM部署,好多同學(xué)第一步就被勸退了,那么如何繞過這個步驟先學(xué)習(xí)LLM模型的應(yīng)用,對Langchain進行快速上手?本片講解3個把LangChain跑起來
  • 服務(wù)存儲設(shè)計模式:Cache-Aside模式

    Cache-Aside模式一種常用的緩存方式,通常是把數(shù)據(jù)從主存儲加載到KV緩存中,加速后續(xù)的訪問。在存在重復(fù)度的場景,Cache-Aside可以提升服務(wù)性能,降低底層存儲的壓力,缺點是緩存和底
  • 多線程開發(fā)帶來的問題與解決方法

    使用多線程主要會帶來以下幾個問題:(一)線程安全問題  線程安全問題指的是在某一線程從開始訪問到結(jié)束訪問某一數(shù)據(jù)期間,該數(shù)據(jù)被其他的線程所修改,那么對于當(dāng)前線程而言,該線程
  • 三萬字盤點 Spring 九大核心基礎(chǔ)功能

    大家好,我是三友~~今天來跟大家聊一聊Spring的9大核心基礎(chǔ)功能。話不多說,先上目錄:圖片友情提示,本文過長,建議收藏,嘿嘿嘿!一、資源管理資源管理是Spring的一個核心的基礎(chǔ)功能,不
  • 拼多多APP上線本地生活入口,群雄逐鹿萬億市場

    Tech星球(微信ID:tech618)文 | 陳橋輝 Tech星球獨家獲悉,拼多多在其APP內(nèi)上線了&ldquo;本地生活&rdquo;入口,位置較深,位于首頁的&ldquo;充值中心&rdquo;內(nèi),目前主要售賣美食相關(guān)的
  • 認真聊聊東方甄選:如何告別低垂的果實

    來源:山核桃作者:財經(jīng)無忌爆火一年后,俞敏洪和他的東方甄選依舊是頗受外界關(guān)心的&ldquo;網(wǎng)紅&rdquo;。7月5日至9日,為期5天的東方甄選&ldquo;甘肅行&rdquo;首次在自有App內(nèi)直播,
  • 首發(fā)天璣9200+ iQOO Neo8系列發(fā)布首銷售價2299元起

    2023年5月23日晚,iQOO Neo8系列正式發(fā)布。其中,Neo系列首款Pro之作——iQOO Neo8 Pro強悍登場,限時售價3099元起;價位段最強性能手機iQOO Neo8同期上市
Top 主站蜘蛛池模板: 汤原县| 白沙| 湘潭县| 晋江市| 泊头市| 连州市| 那坡县| 汕尾市| 安图县| 洪洞县| 高雄市| 仙桃市| 七台河市| 哈密市| 广安市| 乌审旗| 新余市| 仪陇县| 阳原县| 闽清县| 雷波县| 雷州市| 施甸县| 洛浦县| 日喀则市| 沭阳县| 北安市| 岗巴县| 莫力| 彭阳县| 上蔡县| 泸州市| 五华县| 顺昌县| 门源| 临邑县| 宝坻区| 饶平县| 临漳县| 高邮市| 桃园市|