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

當前位置:首頁 > 科技  > 軟件

Java新的結構化并行模式入門指南

來源: 責編: 時間:2023-12-26 09:29:18 328觀看
導讀譯者 | 布加迪審校 | 重樓結構化并發是Java中使用多線程的一種新方式。它允許開發人員在充分利用傳統線程和虛擬線程的同時考慮邏輯組中的工作。結構化并發出現在Java 21的預覽版中,它是決定Java未來的一個關鍵方面,所

譯者 | 布加迪jje28資訊網——每日最新資訊28at.com

審校 | 重樓jje28資訊網——每日最新資訊28at.com

結構化并發是Java中使用多線程的一種新方式。它允許開發人員在充分利用傳統線程和虛擬線程的同時考慮邏輯組中的工作。結構化并發出現在Java 21的預覽版中,決定Java未來的一個關鍵方面,所以現在是開始使用它的好時機。jje28資訊網——每日最新資訊28at.com

jje28資訊網——每日最新資訊28at.com

為什么我們需要結構化并發

編寫并發軟件是軟件開發面臨的最大挑戰之一。Java的線程模使其成為并發語言中的有力競爭者,但是多線程一直天生很棘手。結構化并發允許您使用具有結構化編程語法的多線程。實質上,它提供了一種使用熟悉的程序流程和構編寫并發軟件的方法。這讓開發可以專注于手頭的事務,而不是線程編排。正如結構化并發性的JEP所說:“如果一個任務分成并發子任務,它們都回到相同的位置,即任務的代碼塊。jje28資訊網——每日最新資訊28at.com

虛擬線程現在是Java的一正式特性,它可以低成本生成線程,從而獲得并發性能。結構化并發提供了這做的簡單語法。因此,Java現在有了一個獨特的、高度優化的線程系統,而且易于理解jje28資訊網——每日最新資訊28at.com

新的StructuredTaskScope類

結構化并發中的主要類是java.util.concurrent.StructuredTaskScopeJava 21文檔包含如何使用結構化并發的示例。截止本文發稿時,您需要使用--enable-preview--source 21--source 22來啟用Java程序中的結構化并發。我的$java --versionopenjdk 22-ea,所以我們使用Maven例將為編譯步驟指定--enable-preview --source 22,為執行步驟指定--enable-preview。注意,SDKMan對于管理多個JDK安裝是一個很好的選擇。jje28資訊網——每日最新資訊28at.com

您可以在本文的GitHub代碼存儲庫中找到示例代碼。注意為執行設置enable-preview的.mvn/jvm.config文件。若要運行代碼,使用$mvn clean compile exec:javajje28資訊網——每日最新資訊28at.com

具有結構化并發的多線程

就本文示例而言,我們將向Star Wars APISWAPI發出幾個請求,通過行星的ID獲取有關行星的信息。如果我們在標準的同步Java中執行此操作,可能會使用Apache HTTPClient執行類似代碼片段1的操作。jje28資訊網——每日最新資訊28at.com

代碼片段1. 類似傳統方法的多API調用

package com.infoworld;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.util.EntityUtils;public class App { public String getPlanet(int planetId) throws Exception { System.out.println("BEGIN getPlanet()"); String url = "https://swapi.dev/api/planets/" + planetId + "/"; String ret = "?"; CloseableHttpClient httpClient = HttpClients.createDefault(); HttpGet request = new HttpGet(url); CloseableHttpResponse response = httpClient.execute(request); // Check the response status code if (response.getStatusLine().getStatusCode() != 200) { System.err.println("Error fetching planet information for ID: " + planetId); throw new RuntimeException("Error fetching planet information for ID: " + planetId); } else { // Parse the JSON response and extract planet information ret = EntityUtils.toString(response.getEntity()); System.out.println("Got a Planet: " + ret); } // Close the HTTP response and client response.close(); httpClient.close(); return ret; }  void sync() throws Exception { int[] planetIds = {1,2,3,4,5}; for (int planetId : planetIds) { getPlanet(planetId); } } public static void main(String[] args) { var myApp = new App(); System.out.println("/n/r-- BEGIN Sync"); try { myApp.sync(); } catch (Exception e){ System.err.println("Error: " + e); } }}

在代碼片段1中,我們有一個調用sync()方法的主方法,該方法在調用“https://swapi.dev/api/planets/”+ planetId端點時,只是對一組ID進行迭代處理。這些調用通過getPlanet()方法發出,該方法使用Apache HTTP庫來處理樣板請求、響應和錯誤處理。實際上,該方法接收每個響應,如果正確200輸出到控制臺否則拋出錯誤。這些例使用了最少的錯誤,所以在這種情況下我們只拋出RuntimeException。jje28資訊網——每日最新資訊28at.com

輸出是這樣的jje28資訊網——每日最新資訊28at.com

-- BEGIN SyncBEGIN getPlanet()Got a Planet: {"name":"Tatooine"} BEGIN getPlanet()Got a Planet: {"name":"Alderaan"}BEGIN getPlanet()Got a Planet: {"name":"Yavin”}BEGIN getPlanet()Got a Planet: {"name":"Hoth"}BEGIN getPlanet()Got a Planet: {"name":"Dagobah"}

現在不妨使用結構化并發嘗試同一個示例。如代碼片段2所示,結構化并發允許我們將調用分解并發請求,并將所有內容在相同的代碼空間中。在代碼片段2中,我們添加了必要的StructuredTaskScope導入,然后使用核心方法fork()和join()將每個請求分解成各自的線程,然后等待它們全部完成。jje28資訊網——每日最新資訊28at.com

代碼片段2. 使用StructuredTaskScopeNow多API調用

package com.infoworld;import java.util.concurrent.*;import java.util.concurrent.StructuredTaskScope.*;//...public class App { public String getPlanet(int planetId) throws Exception { // ... same ... } void sync() throws Exception { int[] planetIds = {1,2,3,4,5}; for (int planetId : planetIds) { getPlanet(planetId); } } void sc() throws Exception { int[] planetIds = {1,2,3,4,5}; try (var scope = new StructuredTaskScope<Object>()) { for (int planetId : planetIds) { scope.fork(() -> getPlanet(planetId)); }  scope.join(); }catch (Exception e){ System.out.println("Error: " + e); } } public static void main(String[] args) { var myApp = new App(); // ... System.out.println("/n/r-- BEGIN Structured Concurrency"); try { myApp.sc(); } catch (Exception e){ System.err.println("Error: " + e); }  }}

如果我們運行代碼片段2,將得到類似的輸出,但速度要快不少這是由于請求是同時發出并發進行的。不妨考慮sc()方法使用多線程與sync()方法使用同步代碼之間的區別。結構化并發方法沒有想象的那么難,提供結果的速度卻快得多。jje28資訊網——每日最新資訊28at.com

處理任務和子任務

默認情況下,StructuredTaskScope被創建時,它使用虛擬線程,所以我們實際上并沒有在這里配置操作系統線程相反,我們告訴JVM以最有效的方式編排請求。StructuredTaskScope的構造函數也接受ThreadFactory。jje28資訊網——每日最新資訊28at.com

代碼片段2中,我們在try-with-resource塊中創建StructuredTaskScope對象,這是它原本的使用方式。我們可以使用fork()創建任意數量的作業。fork()方法接受任何實現Callable的程序,也就是說,任何方法或函數。這里,我們將getPlanet()方法包裝在一個匿名函數中()-> getPlanet(planetId)——這是一種向目標函數傳遞參數的用語法。jje28資訊網——每日最新資訊28at.com

我們調用join()時,我們告訴作用域等待所有被分叉的作業。實質上,join()將我們帶回到同步模式。分叉的作業將按照TaskScope的配置進行處理jje28資訊網——每日最新資訊28at.com

閉任務作用域

由于我們在try-with-resource塊中創建了TaskScope,因此當該塊結束時,作用域將自動關閉。這為作用域調用shutdown()進程,作用域可以定制,以便根據需要處理運行線程的處置。如果需要在作用域關閉之前關閉它,也可以手動調用shutdown()方法。jje28資訊網——每日最新資訊28at.com

StructuredTaskScope包括兩個實現內置關閉策略的類ShutDownOnSuccess和ShutDownOnFailure。這些監視成功或出錯的子任務,然后取消其余運行的線程。使用目前的設置,我們可以這樣使用這些類jje28資訊網——每日最新資訊28at.com

代碼片段3. 內置關閉策略

void failFast() throws ExecutionException, InterruptedException { int[] planetIds = {1,2,3,-1,4}; try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { for (int planetId : planetIds) { scope.fork(() -> getPlanet(planetId)); }  scope.join(); } } void succeedFast() throws ExecutionException, InterruptedException { int[] planetIds = {1,2}; try (var scope = new StructuredTaskScope.ShutdownOnSuccess()) { for (int planetId : planetIds) { scope.fork(() -> getPlanet(planetId)); }  scope.join(); } catch (Exception e){ System.out.println("Error: " + e); }} public static void main(String[] args) { var myApp = new App(); System.out.println("/n/r-- BEGIN succeedFast"); try { myApp. succeedFast(); } catch (Exception e) { System.out.println(e.getMessage()); }  System.out.println("/n/r-- BEGIN failFast"); try { myApp.failFast(); } catch (Exception e) { System.out.println(e.getMessage()); } }

些策略將給出類似以下的輸出jje28資訊網——每日最新資訊28at.com

-- BEGIN succeedFastBEGIN getPlanet()BEGIN getPlanet()Got a Planet: {"name":"Alderaan"}org.apache.http.impl.execchain.RetryExec executeINFO: I/O exception (java.net.SocketException) caught when processing request to {s}->https://swapi.dev:443: Closed by interrupt-- BEGIN failFastBEGIN getPlanet()BEGIN getPlanet()BEGIN getPlanet()BEGIN getPlanet()BEGIN getPlanet()Got a Planet: {"name":"Hoth"}Got a Planet: {"name":"Tatooine"}Error fetching planet information for ID: -1org.apache.http.impl.execchain.RetryExec executeINFO: I/O exception (java.net.SocketException) caught when processing request to {s}->https://swapi.dev:443: Closed by interrupt

因此,我們擁有的是一種簡單的機制,可以并發啟動所有請求,然后在一個請求成功或失敗時取消其余的請求。這里,可以進行任何定制。結構化并發文檔包括一個示例,在子任務成功或失敗時收集子任務結果,然后返回結果。這很容易完成,只需通過覆蓋join()方法并觀察每個任務的結果。jje28資訊網——每日最新資訊28at.com

StructuredTaskScope.Subtask

在我們的示例中沒有看到的一件事是觀察子任務的返回值。每次StructuredTaskScope.fork()被調用時,就返回StructuredTaskScope.SubTask對象。我們可以利用它來觀察任務的狀態。比如在sc()方法中,我們可以這jje28資訊網——每日最新資訊28at.com

代碼片段4. 使用StructuredTaskScope.Subtask觀察狀態

import java.util.concurrent.StructuredTaskScope.Subtask;import java.util.ArrayList;void sc() throws Exception { int[] planetIds = {1,2,3,4,5}; ArrayList<Subtask> tasks = new ArrayList<Subtask>(planetIds.length);  try (var scope = new StructuredTaskScope<Object>()) { for (int planetId : planetIds) { tasks.add(scope.fork(() -> getPlanet(planetId))); }  scope.join(); }catch (Exception e){ System.out.println("Error: " + e); } for (Subtask t : tasks){ System.out.println("Task: " + t.state()); } }

在這個例中,我們將每個任務保存在ArrayList中,然后在進行join()操作之后輸出它們的狀態。注意,Subtask的可用狀態被定義為enum。這個新方法將輸出類似以下的內容jje28資訊網——每日最新資訊28at.com

-- BEGIN Structured ConcurrencyBEGIN getPlanet()BEGIN getPlanet()BEGIN getPlanet()BEGIN getPlanet()BEGIN getPlanet()Got a Planet: {"name":"Dagobah"}Got a Planet: {"name":"Hoth"}Got a Planet: {"name":"Tatooine"}Got a Planet: {"name":"Yavin IV"}Got a Planet: {"name":"Alderaan"}Task: SUCCESSTask: SUCCESSTask: SUCCESSTask: SUCCESSTask: SUCCESS

結論

在虛擬線程和結構化并發之間,Java開發擁有一種引人注目的新機制,可以將幾乎所有代碼分解并發任務,不會大的開銷。上下文和需求很重要,所以不要僅僅因為存在這些新的并發工具就使用它們。與此同時,這種組合確實提供了一些強大的力量。一旦您遇到出現許多任務的瓶頸時,您可以輕松地將它們全部交給虛擬線程引擎,該引擎將找到編排它們的最佳方法。具有結構化并發的新線程模式還使您易于定制和微調這種行jje28資訊網——每日最新資訊28at.com

至于開發者將來如何在我們的應用程序、框架和服務器中使用這些新的并發功能,值得我們拭目以待jje28資訊網——每日最新資訊28at.com

小知識:結構化并發中的線程樹

結構化并發包括對調試和理解線程之間關系的支持。特別是,結構化并發將所有線程關聯到樹結構中,作用域位于根。這樣一來,查看線程之間的關系就變得很簡單,即便使用嵌套作用域也是如此。說明文檔提供了一個好的示例,表明如何使用Java診斷命令(jcmd)實用程序,將線程的運行時布局轉儲到控制臺。jje28資訊網——每日最新資訊28at.com

原文標題:Get started with Java's new structured concurrency model,作者:Matthew Tysonjje28資訊網——每日最新資訊28at.com


jje28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-54131-0.htmlJava新的結構化并行模式入門指南

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

上一篇: 企業快成長 AI 技術創新論壇?深圳站:讓創新創意肆意生長

下一篇: 分布式場景下的事務機制

標簽:
  • 熱門焦點
  • 石頭自清潔掃拖機器人G10S評測:多年黑科技集大成之作 懶人終極福音

    科技圈經常能看到一個詞叫“縫合怪”,用來形容那些把好多功能或者外觀結合在一起的產品,通常這樣的詞是貶義詞,但如果真的是產品縫合的好、縫合的實用的話,那它就成了中性詞,今
  • K8S | Service服務發現

    一、背景在微服務架構中,這里以開發環境「Dev」為基礎來描述,在K8S集群中通常會開放:路由網關、注冊中心、配置中心等相關服務,可以被集群外部訪問;圖片對于測試「Tes」環境或者
  • 使用LLM插件從命令行訪問Llama 2

    最近的一個大新聞是Meta AI推出了新的開源授權的大型語言模型Llama 2。這是一項非常重要的進展:Llama 2可免費用于研究和商業用途。(幾小時前,swyy發現它已從LLaMA 2更名為Lla
  • 慕巖炮轟抖音,百合網今何在?

    來源:價值研究所 作者:Hernanderz&ldquo;難道就因為自己的一個產品牛逼了,從客服到總裁,都不愿意正視自己產品和運營上的問題,選擇逃避了嗎?&rdquo;這一番話,出自百合網聯合創
  • 騰訊VS網易,最卷游戲暑期檔,誰能笑到最后?

    作者:無銹缽來源:財經無忌7月16日晚,上海1862時尚藝術中心。伴隨著幻象的精準命中,碩大的熒幕之上,比分被定格在了14:12,被寄予厚望的EDG戰隊以絕對的優勢戰勝了BLG戰隊,拿下了總決
  • ESG的面子與里子

    來源 | 光子星球撰文 | 吳坤諺編輯 | 吳先之三伏大幕拉起,各地高溫預警不絕,但處于厄爾尼諾大&ldquo;烤&rdquo;之下的除了眾生,還有各大企業發布的ESG報告。ESG是&ldquo;環境保
  • 小米公益基金會捐贈2500萬元馳援北京、河北暴雨救災

    8月2日消息,今日小米科技創始人雷軍在其微博上發布消息稱,小米公益基金會宣布捐贈2500萬元馳援北京、河北暴雨救災。攜手抗災,京冀安康!以下為公告原文
  • 三星推出Galaxy Tab S9系列平板電腦以及Galaxy Watch6系列智能手表

    2023年7月26日,三星電子正式發布了Galaxy Z Flip5與Galaxy Z Fold5。除此之外,Galaxy Tab S9系列平板電腦以及三星Galaxy Watch6系列智能手表也同期
  • Android 14發布:首批適配機型公布

    5月11日消息,谷歌在今天凌晨舉行了I/O大會,本次發布會谷歌帶來了自家的AI語言模型PaLM 2、谷歌Pixel Fold折疊屏、谷歌Pixel 7a手機,同時發布了Androi
Top 主站蜘蛛池模板: 安龙县| 凤城市| 堆龙德庆县| 栖霞市| 安仁县| 乌鲁木齐县| 鱼台县| 宁城县| 韶山市| 孝昌县| 汤原县| 交口县| 余姚市| 大庆市| 新竹市| 安阳县| 江陵县| 南投市| 安吉县| 彭泽县| 元朗区| 金秀| 嵊州市| 周宁县| 辰溪县| 姚安县| 根河市| 镇宁| 伊宁市| 棋牌| 景东| 台北县| 新丰县| 东至县| 杭州市| 武夷山市| 黄大仙区| 巴塘县| 古丈县| 伽师县| 札达县|