日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java 8中的并行和异步编程

發(fā)布時(shí)間:2023/12/3 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 8中的并行和异步编程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

并行代碼是在多個(gè)線程上運(yùn)行的代碼,曾經(jīng)是許多經(jīng)驗(yàn)豐富的開發(fā)人員的噩夢,但是Java 8帶來了許多更改,這些更改應(yīng)該使這種提高性能的技巧更加易于管理。

并行流

在Java 8之前,并行(或并發(fā))代碼與順序代碼之間存在很大差異。 調(diào)試非順序代碼也非常困難。 只需像通常那樣設(shè)置一個(gè)斷點(diǎn)并按照流程進(jìn)行操作,就可以刪除并行方面,如果這是導(dǎo)致該錯(cuò)誤的原因,那么這是一個(gè)問題。

幸運(yùn)的是,Java 8為我們提供了流,這是自Bean以來對Java開發(fā)人員而言最大的事情。 如果您不知道它們是什么,則Stream API可以處理功能問題中的元素序列。 (在這里檢查流與.NET的LINQ之間的比較。)流的優(yōu)點(diǎn)之一是代碼的結(jié)構(gòu)保持不變:無論是順序的還是并發(fā)的,它都保持可讀性。

為了使您的代碼并行運(yùn)行,您只需使用.parallelStream()而不是.stream() (或者,如果您不是流的創(chuàng)建者,則可以使用stream .parallel() )。

但是,僅僅因?yàn)樗苋菀?#xff0c;并不意味著并行代碼始終是最佳選擇。 您應(yīng)該始終考慮對代碼使用并發(fā)是否有意義。 該決定中最重要的因素將是速度:僅當(dāng)并發(fā)使您的代碼比其順序?qū)?yīng)的代碼更快時(shí)才使用并發(fā)。

速度問題

并行代碼通過使用多個(gè)線程而不是順序代碼使用的單個(gè)線程而獲得了速度優(yōu)勢。 確定創(chuàng)建多少個(gè)線程可能是一個(gè)棘手的問題,因?yàn)楦嗟木€程并不總是會導(dǎo)致更快的代碼:如果使用太多的線程,則代碼的性能實(shí)際上可能會下降。

有幾個(gè)規(guī)則可以告訴您選擇多少線程。 這主要取決于您要執(zhí)行的操作類型以及可用內(nèi)核的數(shù)量。

計(jì)算密集型操作應(yīng)使用少于或等于內(nèi)核數(shù)的線程數(shù),而IO密集型操作(如復(fù)制文件)對CPU無用,因此可以使用更多線程。 該代碼不知道哪種情況適用,除非您告訴它該怎么做。 否則,它將默認(rèn)為線程數(shù)等于內(nèi)核數(shù)。

在兩種主要情況下,并行運(yùn)行代碼而不是順序運(yùn)行代碼很有用:耗時(shí)的任務(wù)和在大集合上運(yùn)行的任務(wù)。 Java 8帶來了一種處理大集合的新方法,即使用流。 流具有惰性的內(nèi)置效率:它們使用惰性評估,通過不做不必要的事情來節(jié)省資源。 這與并行性不同,只要它運(yùn)行得更快,它就不會在乎資源。 因此,對于大型集合,您可能不需要經(jīng)典的并行性。

================================================== ====================

異步

JavaScript的教訓(xùn)

Java開發(fā)人員很少會說他們從看過JavaScript中學(xué)到了什么,但是在異步編程方面,JavaScript實(shí)際上是正確的。 作為一種從根本上異步的語言,JavaScript經(jīng)驗(yàn)豐富,如果實(shí)施不好,它會帶來多大的痛苦。 它從回調(diào)開始,后來被promise取代。 許諾的一個(gè)重要好處是它有兩個(gè)“通道”:一個(gè)用于數(shù)據(jù),另一個(gè)用于錯(cuò)誤。 JavaScript承諾可能看起來像這樣:

func .then(f1) .catch(e1) .then(f2) .catch(e2);

因此,當(dāng)原始函數(shù)獲得成功結(jié)果時(shí),將調(diào)用f1,但是如果引發(fā)錯(cuò)誤,則將調(diào)用e1。 這可能會將其帶回到成功軌道(f2),或?qū)е铝硪粋€(gè)錯(cuò)誤(e2)。 您可以從數(shù)據(jù)跟蹤到錯(cuò)誤跟蹤再返回。

JavaScript承諾的Java版本稱為CompletableFuture 。

未來發(fā)展

CompletableFuture同時(shí)實(shí)現(xiàn)Future和CompletionStage接口。 Java8之前就已經(jīng)存在Future ,但是它本身對開發(fā)人員并不十分友好。 您只能使用.get()方法獲得異步計(jì)算的結(jié)果,該方法會阻塞其余部分(使異步部分大部分時(shí)間變得毫無意義),并且您需要手動實(shí)現(xiàn)每種情況。 添加CompletionStage接口是使Java異步編程可行的突破。

CompletionStage是一個(gè)承諾,即最終將完成計(jì)算的承諾。 它包含許多方法,可讓您附加將在完成時(shí)執(zhí)行的回調(diào)。 現(xiàn)在我們可以處理結(jié)果而不會阻塞。

有兩種主要方法可讓您啟動代碼的異步部分: supplyAsync如果您想對方法的結(jié)果做一些事情)和runAsync如果您不想這樣做)。

CompletableFuture.runAsync(() → System.out.println("Run async in completable future " + Thread.currentThread())); CompletableFuture.supplyAsync(() → 5);

回呼

現(xiàn)在,您可以添加這些回調(diào)以處理supplyAsync的結(jié)果

CompletableFuture.supplyAsync(() → 5) .thenApply(i → i * 3) .thenAccept(i → System.out.println(“The result is “ + i) .thenRun(() → System.out.println("Finished."));

.thenApply與.thenApply的.map函數(shù)相似:它執(zhí)行轉(zhuǎn)換。 在上面的示例中,它將結(jié)果(5)乘以3。然后將結(jié)果(15)進(jìn)一步傳遞給管道。

.thenAccept對結(jié)果執(zhí)行一種方法,而無需對其進(jìn)行轉(zhuǎn)換。 它也不會返回結(jié)果。 它將在控制臺上顯示“結(jié)果為15”。 可以將它與.foreach方法進(jìn)行流比較。

.thenRun不使用異步操作的結(jié)果,也不返回任何內(nèi)容,它只是等待調(diào)用其Runnable直到上一步完成為止。

異步處理

上述所有回調(diào)方法也都具有異步版本: thenRunAsync , thenApplyAsync等。這些版本可以在自己的線程上運(yùn)行,它們?yōu)槟峁┝祟~外的控制權(quán),因?yàn)槟梢愿嬖V它要使用哪個(gè)ForkJoinPool 。

如果您不使用異步版本,則所有回調(diào)將在同一線程上執(zhí)行。

當(dāng)事情出錯(cuò)時(shí)

當(dāng)出現(xiàn)問題時(shí),將使用exceptionally方法來處理異常。 您可以給它提供一個(gè)方法,該方法返回一個(gè)值以返回?cái)?shù)據(jù)軌道,或引發(fā)(新)異常。

… .exceptionally(ex → new Foo()) .thenAccept(this::bar);

合并和撰寫

您可以使用thenCompose方法鏈接多個(gè)CompletableFutures 。 沒有它,結(jié)果將嵌套CompletableFutures 。 這使得thenCompose和thenApply像flatMap和map用于流。

CompletableFuture.supplyAsync(() -> "Hello") .thenCompose(s -> CompletableFuture .supplyAsync(() -> s + "World"));

如果要合并兩個(gè)CompletableFutures的結(jié)果,則需要一個(gè)方便地稱為thenCombine的方法。

future.thenCombine(future2, Integer::sum) .thenAccept(value → System.out.println(value));

如您在上面的示例中看到的那樣,可以使用所有喜歡的CompletionStage方法像普通的CompletableFuture一樣處理thenCombine中的回調(diào)結(jié)果。

結(jié)論

在尋求更快的代碼時(shí),并行編程不再是不可克服的障礙。 Java 8使該過程盡可能簡單明了,因此,可能從中受益的任何代碼都可以在所有線程上被拉,踢和尖叫,進(jìn)入多核未來,而實(shí)際上,這只是現(xiàn)在天。 我的意思是:這很容易做到,因此請嘗試一下,看看自己的優(yōu)勢。

翻譯自: https://www.javacodegeeks.com/2018/04/parallel-and-asynchronous-programming-in-java-8.html

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的Java 8中的并行和异步编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。