CompletableFuture使用詳解(Super Detailed)

一、 CompletableFuture介紹
多線程開發一般使用Runnable,Callable,Thread,FutureTask,ThreadPoolExecutor,但也有不近如意的地方

Thread + Runnable:執行異步任務,沒有返回結果。
Thread + Callable + FutureTask:執行一步任務,有返回結果。

獲取返回結果,基于get方法獲取,線程需要掛起在WaitNode里。
獲取返回結果,基于isDone判斷任務的狀態,但是這里需要不斷輪詢。

上述的方式都是有一定的局限性的
CompletableFuture是Java 8中引入的一種實現異步編程模型的方式,它是Future的擴展,提供了更強大、更靈活的功能。CompletableFuture可以表示兩個異步任務之間的順序關系或并行關系,同時提供了一些方便的工具方法來組合這些關系。
二、 應用
首先對CompletableFuture提供的函數式編程中三個函數有一個掌握

Supplier 生產者,沒有入參,有返回結果
Consumer 消費者,有入參,但是沒有返回結果
Function<T,U> 函數,有入參,又有返回結果

2.1 功能
并行執行

allOf():當所有給定的 CompletableFuture 完成時,返回一個新的 CompletableFuture 。
anyOf():當任何一個給定的CompletablFuture完成時,返回一個新的CompletableFutur。

依賴關系

thenApply():把前面任務的執行結果,交給后面的Function。
thenCompose():用來連接兩個有依賴關系的任務,結果由第二個任務返回。

or聚合關系

applyToEither():兩個任務哪個執行的快,就使用哪一個結果,有返回值 。
acceptEither():兩個任務哪個執行的快,就消費哪一個結果,無返回值 。
runAfterEither():任意一個任務執行完成,進行下一步操作(Runnable類型任務。

and集合關系

thenCombine():合并任務,有返回值 。
thenAccepetBoth():兩個任務執行完成后,將結果交給thenAccepetBoth處理,無返回值 。
runAfterBoth():兩個任務都執行完成后,執行下一步操作(Runnable類型任務。

結果處理

whenComplete:當任務完成時,將使用結果(或 null)和此階段的異常(或 null如果沒有)執行給定操作。
exceptionally:返回一個新的CompletableFuture,當前面的CompletableFuture完成時,它也完成,當它異常完成時,給定函數的異常觸發這個CompletableFuture的完成。

2.2 supplyAsync
CompletableFuture如果不提供線程池的話,默認使用的ForkJoinPool,而ForkJoinPool內部是守護線程,如果main線程結束了,守護線程會跟著一起結束。
java 體驗AI代碼助手 代碼解讀復制代碼 public static void main(String[] args) {
CompletableFuture firstTask = CompletableFuture.supplyAsync(() -> {
System.out.println(“task begin!”);
System.out.println(“task end!”);
return “result”;
});

String result1 = firstTask.join();
String result2 = null;
try {result2 = firstTask.get();
} catch (InterruptedException e) {e.printStackTrace();
} catch (ExecutionException e) {e.printStackTrace();
}System.out.println(result1 + "," + result2);

}

2.3 runAsync
當前方式既不會接收參數,也不會返回任何結果,非常基礎的任務編排方式
java 體驗AI代碼助手 代碼解讀復制代碼 public static void main(String[] args) throws IOException {
CompletableFuture.runAsync(() -> {
System.out.println(“task begin!”);
System.out.println(“task end!”);
});

System.in.read();

}

2.4 thenApply,thenApplyAsync
有任務A,還有任務B。任務B需要在任務A執行完畢后再執行。而且任務B需要任務A的返回結果。
任務B自身也有返回結果。thenApply可以拼接異步任務,前置任務處理完之后,將返回結果交給后置任務,然后后置任務再執行thenApply提供了帶有Async的方法,可以指定每個任務使用的具體線程池。
thenApply:
java 體驗AI代碼助手 代碼解讀復制代碼 public static void main(String[] args) {
CompletableFuture taskA = CompletableFuture.supplyAsync(() -> {
String id = UUID.randomUUID().toString();
System.out.println(“taskA:” + id);
return id;
});
CompletableFuture taskB = taskA.thenApply(result -> {
System.out.println(“taskA resule:” + result);
result = result.replace(“-”, “”);
return result;
});

    System.out.println("main task deal result:" + taskB.join());
}

thenApplyAsync:
java 體驗AI代碼助手 代碼解讀復制代碼 public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(10);
CompletableFuture taskB = CompletableFuture.supplyAsync(() -> {
String id = UUID.randomUUID().toString();
System.out.println(“taskA:” + id + “,” + Thread.currentThread().getName());
return id;
}).thenApplyAsync(result -> {
System.out.println(“taskB get taskA result:” + result + “,” + Thread.currentThread().getName());
result = result.replace(“-”, “”);
return result;
},executor);

    System.out.println("main thread:" + taskB.join());
}

2.5 thenAccept,thenAcceptAsync(自定義線程池)
套路和thenApply一樣,都是任務A和任務B的拼接前置任務需要有返回結果,后置任務會接收前置任務的結果,返回后置任務,沒有返回值
java 體驗AI代碼助手 代碼解讀復制代碼 public static void main(String[] args) throws IOException {
CompletableFuture.supplyAsync(() -> {
System.out.println(“taskA”);
return “abcdefg”;
}).thenAccept(result -> {
System.out.println(“taskB,get result:” + result);
});
System.in.read();
}

2.6 thenRun,thenRunAsync(自定義線程池)
套路和thenApply,thenAccept一樣,都是任務A和任務B的拼接,前置任務沒有返回結果,后置任務不接收前置任務結果,后置任務也沒有返回結果。
java 體驗AI代碼助手 代碼解讀復制代碼 public static void main(String[] args) throws IOException {
CompletableFuture.runAsync(() -> {
System.out.println(“taskA begin!”);
}).thenRun(() -> {
System.out.println(“taskB begin!”);
});
System.in.read();
}

2.7 thenCombine,thenAcceptBoth,runAfterBoth
比如有任務A,任務B,任務C。任務A和任務B并行執行,等到任務A和任務B全部執行完畢后,再執行任務C。
2.7.1 thenCombine
當前方式當前方式前置任務需要有返回結果,后置任務接收前置任務的結果,有返回值
java 體驗AI代碼助手 代碼解讀復制代碼 public static void main(String[] args) {
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
System.out.println(“taskA begin!!”);
return 10;
}).thenCombine(CompletableFuture.supplyAsync(() -> {
System.out.println(“taskB begin!!”);
return 10;
}), (r1, r2) -> {
System.out.println(“taskC begin!!”);
return r1 + r2;
});
System.out.println("taskC result = " + future.join());
}

2.7.2 thenAcceptBoth
當前方式前置任務需要有返回結果,后置任務接收前置任務的結果,沒有返回值
java 體驗AI代碼助手 代碼解讀復制代碼 public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
System.out.println(“taskA begin!!”);
return 10;
}).thenAcceptBoth(CompletableFuture.supplyAsync(() -> {
System.out.println(“taskB begin!!”);
return 10;
}), (r1, r2) -> {
System.out.println(“taskC begin!!”);
int r = r2 + r1;
System.out.println("taskC result = " + r);
});
}

2.7.3 runAfterBoth
當前方式前置任務不需要有返回結果,后置任務不會接收前置任務的結果,沒有返回值
java 體驗AI代碼助手 代碼解讀復制代碼 public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
System.out.println(“taskA begin!!”);
return 10;
}).runAfterBoth(CompletableFuture.supplyAsync(() -> {
System.out.println(“taskB begin!!”);
return 10;
}), () -> {
System.out.println(“taskC begin!!”);
});
}

2.8 applyToEither,acceptEither,runAfterEither
這三個方法:比如有任務A,任務B,任務C。任務A和任務B并行執行,只要任務A或者任務B執行完畢,開始執行任務C.
applyToEither:可以接收結果并且返回結果,acceptEither:可以接收結果沒有返回結果,runAfterEither:不接收結果也沒返回結果,三個方法拼接任務的方式都是一樣的,applyToEither:只演示一個其它套路一樣。
java 體驗AI代碼助手 代碼解讀復制代碼 public static void main(String[] args) throws IOException {
CompletableFuture taskC = CompletableFuture.supplyAsync(() -> {
System.out.println(“taskA begin!!”);
return 78;
}).applyToEither(CompletableFuture.supplyAsync(() -> {
System.out.println(“taskB begin!!”);
return 66;
}), resultFirst -> {
System.out.println(“taskC begin!!”);
return resultFirst;
});
System.out.println(taskC.join());
System.in.read();
}

2.9 exceptionally,thenCompose,handle
exceptionally:
這個也是拼接任務的方式,但是只有前面業務執行時出現異常了,才會執行當前方法來處理.
只有異常出現時,CompletableFuture的編排任務沒有處理完時,才會觸發。
拿不到任務結果。

whenComplete,handle:
這兩個也是異常處理的套路,可以根據方法描述發現,他的功能方向比exceptionally要更加豐富
whenComplete:
可以拿到返回結果同時也可以拿到出現的異常信息,但是whenComplete本身是Consumer不能返回結果。無法幫你捕獲異常,但是可以拿到異常返回的結果。
handle:
可以拿到返回結果同時也可以拿到出現的異常信息,并且也可以指定返回托底數據。可以捕獲異常的,異常不會拋出去。

java 體驗AI代碼助手 代碼解讀復制代碼 public static void main(String[] args) throws IOException {
CompletableFuture taskC = CompletableFuture.supplyAsync(() -> {
System.out.println(“taskA begin!!”);
return 78;
}).applyToEither(CompletableFuture.supplyAsync(() -> {
System.out.println(“taskB begin!!”);
return 66;
}), resultFirst -> {
System.out.println(“taskC begin!!”);
return resultFirst;
}).handle((r,ex) -> {
System.out.println(“handle:” + r);
System.out.println(“handle:” + ex);
return -1;
});
/.exceptionally(ex -> {
System.out.println(“exceptionally:” + ex);
return -1;
});
/
/.whenComplete((r,ex) -> {
System.out.println(“whenComplete:” + r);
System.out.println(“whenComplete:” + ex);
});
/
System.out.println(taskC.join());
}

2.10 allOf,anyOf
2.10.1 allOf
allOf的方式是讓內部編寫多個CompletableFuture的任務,多個任務都執行完后,才會繼續執行你后續拼接的任務。
allOf返回的CompletableFuture是Void,沒有返回結果
java 體驗AI代碼助手 代碼解讀復制代碼 public static void main(String[] args) throws IOException {
CompletableFuture.allOf(
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“taskA begin!!”);
}),
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“taskB begin!!”);
}),
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“taskC begin!!”);
})
).thenRun(() -> {
System.out.println(“taskD begin!!”);
});

}

2.10.2 anyOf:
anyOf是基于多個CompletableFuture的任務,只要有一個任務執行完畢就繼續執行后續,最先執行完的任務做作為返回結果的入參
java 體驗AI代碼助手 代碼解讀復制代碼 public static void main(String[] args) throws IOException {
CompletableFuture.anyOf(
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“taskA begin!!”);
return “A”;
}),
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“taskB begin!!”);
return “B”;
}),
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“taskC begin!!”);
return “C”;
})
).thenAccept(r -> {
System.out.println(“taskD begin,” + r + “first end”);
});
}

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

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

相關文章

開源 Arkts 鴻蒙應用 開發(六)數據持久--文件和首選項存儲

文章的目的為了記錄使用Arkts 進行Harmony app 開發學習的經歷。本職為嵌入式軟件開發&#xff0c;公司安排開發app&#xff0c;臨時學習&#xff0c;完成app的開發。開發流程和要點有些記憶模糊&#xff0c;趕緊記錄&#xff0c;防止忘記。 相關鏈接&#xff1a; 開源 Arkts …

【Bluedroid】藍牙協議棧控制器能力解析與核心功能配置機制(decode_controller_support)

本文圍繞Bluedroid藍牙協議棧中控制器能力解析與核心功能配置的關鍵代碼展開&#xff0c;詳細闡述藍牙協議棧如何通過解析控制器硬件能力&#xff0c;構建 SCO/eSCO、ACL 數據包類型支持掩碼&#xff0c;配置鏈路策略、安全服務、查詢與掃描模式等核心功能。這些機制確保協議棧…

小架構step系列07:查找日志配置文件

1 概述 日志這里采用logback&#xff0c;其為springboot默認的日志工具。其整體已經被springboot封裝得比較好了&#xff0c;扔個配置文件到classpath里就能夠使用。 但在實際使用中&#xff0c;日志配置文件有可能需要進行改動&#xff0c;比如日志的打印級別&#xff0c;平…

一文講清楚React Hooks

文章目錄一文講清楚React Hooks一、什么是 React Hooks&#xff1f;二、常用基礎 Hooks2.1 useState&#xff1a;狀態管理基本用法特點2.2 useEffect&#xff1a;副作用處理基本用法依賴數組說明2.3 useContext&#xff1a;上下文共享基本用法特點三、其他常用 Hooks3.1 useRed…

Apache http 強制 https

1. 修改一下文件配置 sudo nano /etc/apache2/sites-enabled/000-default.conf<VirtualHost *:80>ServerName hongweizhu.comServerAlias www.hongweizhu.comServerAdmin webmasterlocalhostDocumentRoot /var/www/html# 強制重定向到HTTPSRewriteEngine OnRewriteCond …

【讀代碼】GLM-4.1V-Thinking:開源多模態推理模型的創新實踐

一、基本介紹 1.1 項目背景 GLM-4.1V-Thinking是清華大學KEG實驗室推出的新一代開源視覺語言模型,基于GLM-4-9B-0414基礎模型構建。該項目通過引入"思維范式"和強化學習課程采樣(RLCS)技術,顯著提升了模型在復雜任務中的推理能力。其創新點包括: 64k超長上下文…

從代碼生成到智能運維的革命性變革

AI大模型重塑軟件開發&#xff1a;從代碼生成到智能運維的革命性變革 希望對大家有一定的幫助&#xff0c;進行參考 目錄AI大模型重塑軟件開發&#xff1a;從代碼生成到智能運維的革命性變革 希望對大家有一定的幫助&#xff0c;進行參考一、范式轉移&#xff1a;軟件開發進入&…

豆包編寫Java程序小試

今天下載了一本第四版電氣工程師手冊&#xff0c;非常棒的一本書&#xff0c;在給PDF添加目錄的時候&#xff0c;由于目錄有將近60頁&#xff0c;使用老馬開發的PdgCntEditor有點卡頓&#xff0c;不過補充下&#xff0c;老馬這個PdgCntEditor還是非常好的。所以我決定用Java編一…

SpringBoot整合騰訊云新一代行為驗證碼

一 產品介紹 騰訊云官方介紹鏈接 騰訊云新一代行為驗證碼&#xff08;Captcha&#xff09;&#xff0c;基于十道安全防護策略&#xff0c;為網頁、App、小程序開發者打造立體、全面的人機驗證。在保護注冊登錄、活動秒殺、點贊發帖、數據保護等各大場景下業務安全的同時&…

SenseGlove新一代外骨骼力反饋手套Rembrand來襲!亞毫米級手部動捕+指尖觸覺力采集+5Dof主動力反饋多模態

在遠程機器人操作領域&#xff0c;精準的觸覺感知與靈活的動作控制始終是核心需求。SenseGlove 新推出的 Rembrandt 力反饋外骨骼數據手套&#xff0c;以先進技術為支撐&#xff0c;為遠程操控人形機器人手部提供了無縫解決方案&#xff0c;讓操作更精準、更高效。值得一提的是…

Linux 信號機制:操作系統的“緊急電話”系統

想象一下&#xff0c;你正在電腦前專心工作&#xff0c;突然手機響了——這是一個通知&#xff0c;要求你立即處理一件新事情&#xff08;比如接電話&#xff09;。 Linux 系統中的信號&#xff08;Signal&#xff09;?? 機制&#xff0c;本質上就是操作系統內核或進程之間用…

論文略讀:Prefix-Tuning: Optimizing Continuous Prompts for Generation

2021 ACL固定預訓練LM&#xff0c;為LM添加可訓練&#xff0c;任務特定的前綴這樣就可以為不同任務保存不同的前綴這種前綴可以看成連續可微的soft prompt&#xff0c;相比于離散的token&#xff0c;更好優化&#xff0c;效果更好訓練的時候只需要更新prefix部分的參數&#xf…

CSS基礎選擇器、文本屬性、引入方式及Chorme調試工具

CSS基礎 1.1 CSS簡介 CSS 是層疊樣式表 ( Cascading Style Sheets ) 的簡稱. 有時我們也會稱之為 CSS 樣式表或級聯樣式表。 CSS 是也是一種標記語言 CSS 主要用于設置 HTML 頁面中的文本內容&#xff08;字體、大小、對齊方式等&#xff09;、圖片的外形&#xff08;寬高、邊…

RabbitMQ 高級特性之事務

1. 簡介與 MySQL、Redis 一樣&#xff0c;RabbitMQ 也支持事務。事務中的消息&#xff0c;要么全都發送成功&#xff0c;要么全部發送失敗&#xff0c;不會出現一部分成功一部分失敗的情況。2. 使用事務發送消息spring 中使用 RabbitMQ 開啟事務需要兩步&#xff1a;第一步&…

iframe 的同源限制與反爬機制的沖突

一、事件背景A域名接入了動態防護&#xff08;Bot 防護、反爬蟲機制&#xff09;&#xff0c;同時第三方業務B域名通過內嵌iframe的方式調用了A域名下的一個鏈接。二、動態防護介紹&#xff1a;動態防護&#xff08;也稱為 Bot 防護、反爬蟲機制&#xff09;是網站為了防止自動…

Rust 的 Copy 語義:深入淺出指南

在 Rust 中&#xff0c;Copy 是一個關鍵的特性&#xff0c;它定義了類型的復制行為。理解 Copy 語義對于掌握 Rust 的所有權系統和編寫高效代碼至關重要。一、核心概念&#xff1a;Copy vs Move特性Copy 類型非 Copy 類型 (Move)賦值行為按位復制 (bitwise copy)所有權轉移 (ow…

Qt的信號與槽(二)

Qt的信號與槽&#xff08;二&#xff09;1.自定義槽2.通過圖形化界面來生成自定義槽3.自定義信號3.信號和槽帶參數4.參數數量5.connect函數的設計&#x1f31f;hello&#xff0c;各位讀者大大們你們好呀&#x1f31f;&#x1f31f; &#x1f680;&#x1f680;系列專欄&#xf…

Java研學-MongoDB(三)

三 文檔相關 7 文檔統計查詢① 語法&#xff1a; // 精確統計文檔數 慢 準 dahuang> db.xiaohuang.countDocuments({條件}) 4 // 粗略統計文檔數 快 大致準 dahuang> db.xiaohuang.estimatedDocumentCount({條件}) 4② 例子&#xff1a; // 精確統計文檔數 name為奔波兒灞…

TCP協議格式與連接釋放

TCP報文段格式 TCP雖然是面向字節流的&#xff0c;但TCP傳送帶數據單元確是報文段。TCP報文段分為首部和數據段部分&#xff0c;而TCP的全部功能體現在它在首部中各字段的作用。因此&#xff0c;只有弄清TCP首部各字段的作用才能掌握TCP的工作原理。 TCP報文段首部的前20字節是…

CSS05:結構偽類選擇器和屬性選擇器

結構偽類選擇器 /*ul的第一個子元素*/ ul li:first-child{background: #0af6f6; }/*ul的最后一個子元素*/ ul li:last-child{background: #d27bf3; } /*選中p1&#xff1a;定位到父元素&#xff0c;選擇當前的第一個元素 選擇當前p元素的父級元素&#xff0c;選中父級元素的第…