Java中CompletableFuture異步工具類

參考:CompletableFuture 詳解 | JavaGuide

實際項目中,一個接口可能需要同時獲取多種不同的數據,然后再匯總返回,舉個例子:用戶請求獲取訂單信息,可能需要同時獲取用戶信息、商品詳情、物流信息、等數據。

如果是串行(按順序依次執行每個任務)執行的話,接口的響應速度會非常慢。

考慮到這些任務之間有大部分都是 無前后順序關聯 的,可以 并行執行 ,就比如說調用獲取商品詳情的時候,可以同時調用獲取物流信息。通過并行執行多個任務的方式,接口的響應速度會得到大幅優化。

Future介紹

Future是Java5引入的接口,提供了基本的異步處理功能,但它的局限性在于只能通過 get()方法阻塞獲取結果,無法鏈式調用多個任務,也缺 少異常處理機制。

CompletableFuture 是 Future 的增強版,提供了非阻塞的結果處理、任務組合和異常處理,使得異步編程更加靈活和強大。

在 Java 中,Future 只是一個泛型接口,位于 java.util.concurrent 包下,其中定義了 5 個方法,主要包括下面這 4 個功能:

  • 取消任務;

  • 判斷任務是否被取消;

  • 判斷任務是否已經執行完成;

  • 獲取任務執行結果。

// V 代表了Future執行的任務返回值的類型
public interface Future<V> {// 取消任務執行// 成功取消返回 true,否則返回 falseboolean cancel(boolean mayInterruptIfRunning);// 判斷任務是否被取消boolean isCancelled();// 判斷任務是否已經執行完成boolean isDone();// 獲取任務執行結果V get() throws InterruptedException, ExecutionException;// 指定時間內沒有返回計算結果就拋出 TimeOutException 異常V get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutExceptio
}

CompletableFuture是 java 8引入的一個強大的異步工具類。允許非阻塞地處理異步任務,并且可以通過鏈式調用組合多個異步操作。

public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
}

核心特性如下:

  1. 異步執行

    通過runAsyncsupplyAsync方法,可以異步地執行任務。

  2. 任務完成回調

    使用thenApply、thenAccept、thenRun等方法,可以在任務完成后執行回調。

  3. 任務組合

    可以將多個 CompletableFuture 組合在一起,通過 thenCombine、thenCompose 等方法,處理多個異步任務之間的依賴關系。

  4. 異常處理

    提供了exceptionally、handle等方法,可以在異步任務發生異常時進行處理。

  5. 并行處理

    可以通過allOfanyOf方法,并行地執行多個異步任務,并在所有任務完成或任意一個任務完成時執行回調。

擴展

創建異步任務
  • 通過 new 關鍵字

CompletableFuture<RpcResponse<Object>> resultFuture = new CompletableFuture<>();
//獲取異步計算的結果,調用 get() 方法的線程會 阻塞 直到 CompletableFuture 完成運算
rpcResponse = completableFuture.get(); ?
// complete() 方法只能調用一次,后續調用將被忽略。
resultFuture.complete(rpcResponse);
?
//如果你已經知道計算的結果的話,可以使用靜態方法 completedFuture() 來創建 CompletableFuture 
CompletableFuture<String> future = CompletableFuture.completedFuture("hello!");
assertEquals("hello!", future.get());
  • runAsync: 創建異步任務,不返回結果

  • supplyAsync: 創建異步任務并返回結果

CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> { ?//前面的這個future1不是用來接收數據的,僅僅表示完成狀態// 異步任務
});
?
//future2接收異步執行的結果,即里面返回出來的字符串,后續可以利用thenAccept等方法處理這個結果
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> { // 異步任務并返回結果return "Hello, nihao.com!";
});
任務完成回調
  • thenApply: 在任務完成后可以對任務結果進行轉換返回

  • thenAccept: 在任務完成后對結果進行消費,但不返回新結果

  • thenRun: 在任務完成后執行一個操作,但不需要使用任務結果

// 轉換任務結果
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello").thenApply(result -> result + " nihao.com");// 消費任務結果,不返回新結果
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> "Hello").thenAccept(result -> System.out.println(result));// 不消費任務結果,也不返回新結果
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> "Hello")
.thenRun(() -> System.out.println("Task finished"));
任務組合
  • thenCombine: 合并兩個CompletableFuture 的結果

  • thenCompose: 將一個CompletableFuture 的結果作為另一個 CompletableFuture 的輸入。

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello"); ? //1
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "nihao"); ? //2
?
//future1.thenComebine(fu2,...) 
CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + " " + result2);
?
//將前者的result 傳給 后者
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello").thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " nihao"));
異常處理
  • exceptionally: 在任務發生異常時提供默認值。

  • handle: 在任務完成或發生異常時進行處理。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {if (true) {throw new RuntimeException("Exception");}return "Hello";
}).exceptionally(ex -> "nihao"); ? ? //提供發生異常時的默認值
?
?
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {if (true) {throw new RuntimeException("Exception");}return "Hello";
}).handle((result, ex) -> { ? ? ? //提供發生異常后的處理if (ex != null) {return "Default Value";}return result;
});
并行處理
  • allOf: 等待多個CompletableFuture 全部完成

  • anyOf: 任意一個 CompletableFuture 完成時執行操作

CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);
allFutures.thenRun(() -> System.out.println("nihao tasks finished")); ? ?//全部完成在執行
?
?
CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2);
anyFuture.thenAccept(result -> System.out.println("nihao task finished with result: " + result)); ?//任意一個完成即可執行
使用建議
  • CompletableFuture 默認使用全局共享的 ForkJoinPool.commonPool() 作為執行器,所以應用程序、多個庫或框架(如 Spring、第三方庫)若都依賴 CompletableFuture,默認情況下它們都會共享同一個線程池。

  • 為避免這些問題,建議為 CompletableFuture 提供自定義線程池,根據任務特性調整線程池大小和隊列類型,也更好地處理線程中的異常情況

  • CompletableFutureget()方法是阻塞的,盡量避免使用。如果必須要使用的話,需要添加超時時間,否則可能會導致主線程一直等待,無法執行其他任務。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/70149.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/70149.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/70149.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Oracle Rac 多路徑鏈路不穩定引發IO降速-光弱

一、背景 今天突然被異地的同事拉來開遠程會議&#xff0c;會議內容是開發反饋每天9點左右有個sqlldr 命令的腳本調用突然執行很慢&#xff0c;以前幾秒的導入操作現在需要30-60s左右&#xff0c;而且數據量基本相同。 二、分析 1&#xff09;、查看ASH報告 從報告上確認是數…

哈希表-兩個數的交集

代碼隨想錄-刷題筆記 349. 兩個數組的交集 - 力扣&#xff08;LeetCode&#xff09; 內容: 集合的使用 , 重復的數剔除掉&#xff0c;剩下的即為交集&#xff0c;最后加入數組即可。 class Solution {public int[] intersection(int[] nums1, int[] nums2) {Set<Integer…

[JVM篇]分代垃圾回收

分代垃圾回收 分代收集法是目前大部分 JVM 所采用的方法&#xff0c;其核心思想是根據對象存活的不同生命周期將內存劃分為不同的域&#xff0c;一般情況下將 GC 堆劃分為老生代(Tenured/Old Generation)和新生代(Young Generation)。老生代的特點是每次垃圾回收時只有少量對象…

漢諾塔問題詳解:遞歸與分治的經典案例

嘿&#xff0c;小伙伴們&#xff01;今天我可算撞見了個超有意思的東西&#xff0c;就是那大名鼎鼎的漢諾塔問題&#xff01;我這好奇心一下子就被勾起來了&#xff0c;迫不及待地想深挖一下&#xff0c;然后把那些好玩的、燒腦的、讓人拍案叫絕的解題思路和奇妙故事都分享給大…

vue中如何動態的增減組件的類名(class)

在 Vue.js 2 中&#xff0c;你可以通過計算屬性或直接在模板中使用 v-bind:class 來動態地改變組件的類名。下面是一個簡單的示例&#xff0c;說明如何在某個條件被復核后為組件添加一個 selected 類&#xff08;此處為組件添加一個默認的類&#xff08;例如 radio&#xff09;…

Vue3 基礎概念與環境搭建

一、Vue3 簡介 Vue3 是 Vue.js 的最新主要版本&#xff0c;于 2020 年 9 月正式發布。它在性能、可維護性和開發體驗方面都有了顯著的改進。相比 Vue2&#xff0c;Vue3 的主要特點包括&#xff1a; 更高效的響應式系統&#xff1a;使用 Proxy替代了 Object.defineProperty&…

華為昇騰920b服務器部署DeepSeek翻車現場

最近到禍一臺HUAWEI Kunpeng 920 5250&#xff0c;先看看配置。之前是部署的訊飛大模型&#xff0c;發現資源利用率太低了。把5臺減少到3臺&#xff0c;就出了他 硬件配置信息 基本硬件信息 按照慣例先來看看配置。一共3塊盤&#xff0c;500G的系統盤&#xff0c; 2塊3T固態…

Python的那些事第二十三篇:Express(Node.js)與 Python:一場跨語言的浪漫邂逅

摘要 在當今的編程世界里,Node.js 和 Python 像是兩個性格迥異的超級英雄,一個以速度和靈活性著稱,另一個則以強大和優雅聞名。本文將探討如何通過 Express 框架將 Node.js 和 Python 結合起來,打造出一個高效、有趣的 Web 應用。我們將通過一系列幽默風趣的實例和表格,展…

Word中接入大模型教程

前言 為什么要在word中接入大模型呢&#xff1f; 個人覺得最大的意義就是不用來回切換與復制粘貼了吧。 今天分享一下昨天實踐的在word中接入大模型的教程。 在word中接入大模型最簡單的方式就是使用vba。 vba代碼要做的事&#xff0c;拆分一下就是&#xff1a; 獲取用戶…

open3d繪制平面

在Open3D中繪制平面通常涉及到創建一個平面模型并將其可視化。Open3D是一個開源庫,主要用于3D數據的處理和可視化,但它主要用于3D數據的處理,并不直接支持繪制2D平面。如果你想在Open3D中“繪制”一個平面,你可以通過以下幾種方法來實現類似的效果: 方法1:使用o3d.geome…

DeepSeek R1 與 OpenAI O1:機器學習模型的巔峰對決

我的個人主頁 我的專欄&#xff1a;人工智能領域、java-數據結構、Javase、C語言&#xff0c;希望能幫助到大家&#xff01;&#xff01;&#xff01;點贊&#x1f44d;收藏? 一、引言 在機器學習的廣袤天地中&#xff0c;大型語言模型&#xff08;LLM&#xff09;無疑是最…

WebGPU頂點插槽進階優化指南:釋放GPU渲染性能

本文基于WebGPU官方規范與實踐經驗&#xff0c;深入探討頂點緩沖區的性能優化策略&#xff0c;涵蓋數據布局、資源管理、渲染流程等多個維度&#xff0c;并附詳細代碼注釋與性能對比分析。 一、數據布局優化&#xff1a;降低內存與帶寬壓力 1. 內存對齊策略 GPU對內存訪問有嚴…

數據結構實現順序表的尾插,尾刪,按值查找/修改/刪除,按下標查找/增加/刪除

頭文件&#xff1a;head.h #ifndef __HEAD_H__ #define __HEAD_H__#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAXSIZE 20enum num {success,false-1};typedef int datatype;typedef struct {int len;datatype data[MAXSIZE]; }S…

基于Spring Boot+Vue的寵物服務管理系統(源碼+文檔)

項目簡介 寵物服務管理系統實現了以下功能&#xff1a; 基于Spring BootVue的寵物服務管理系統的主要使用者分為用戶管理模塊&#xff0c;由于系統運行在互聯網絡中&#xff0c;一些游客或者病毒惡意進行注冊&#xff0c;產生大量的垃圾用戶信息&#xff0c;管理員可以對這些…

2. grafana插件安裝并接入zabbix

一、在線安裝 如果不指定安裝位置&#xff0c;則默認安裝位置為/var/lib/grafana/plugins 插件安裝完成之后需要重啟grafana 命令在上一篇講到過 //查看相關幫助 [rootlocalhost ~]# grafana-cli plugins --help //從列舉中的插件過濾zabbix插件 [rootlocalhost ~]# grafana…

【Linux】Ubuntu Linux 系統——Python集成開發環境

??大家好&#xff0c;我是練小杰&#xff0c;今天周四了&#xff0c;明天就周五了&#xff0c;再堅持堅持又能休息了&#xff01;&#xff01;&#x1f606; 本文是有關Linux 操作系統中Python集成開發環境基礎知識&#xff0c;后續將添加更多相關知識噢&#xff0c;謝謝各位…

DeepSeek+即夢 做AI視頻

DeepSeek做AI視頻 制作流程第一步&#xff1a;DeepSeek 生成視頻腳本和分鏡 第二步&#xff1a;生成分鏡圖片繪畫提示詞第三步&#xff1a;生成分鏡圖片第四步&#xff1a;使用可靈 AI 工具&#xff0c;將生成的圖片轉成視頻。第五步&#xff1a;剪映成短視頻 DeepSeek 真的強&…

react傳遞函數與回調函數原理

為什么 React 允許直接傳遞函數&#xff1f; 回調函數核心邏輯 例子&#xff1a;父組件控制 Modal 的顯示與隱藏 // 父組件 (ParentComponent.tsx) import React, { useState } from react; import { Modal, Button } from antd; import ModalContent from ./ModalContent;co…

【Spring AI】基于SpringAI+Vue3+ElementPlus的QA系統實現(前端)

整理不易&#xff0c;請不要吝嗇你的贊和收藏。 1. 前言 這篇文章是 Spring AI Q&A 系統的前端實現。這篇文章將介紹如何快速搭建一個基于 vue3 ElementPlus 的前端項目&#xff0c;vue3 項目的目錄結構介紹&#xff0c;如何在前端實現流式響應&#xff0c;如何高亮顯示…

企業級API集成方案:基于阿里云函數計算調用DeepSeek全解析

解決方案鏈接&#xff1a;https://www.aliyun.com/solution/tech-solution/deepseek-r1-for-platforms?utm_contentg_1000401616 何為DeepSeek R1 DeepSeek R1模型有諸多技術優勢。高效架構設計使其能更高效提取特征&#xff0c;減少冗余計算&#xff0c;提升數據處理速度、…