最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java8 如何正確高效的使用并行流

 更新時(shí)間:2021年11月04日 16:11:38   作者:小小工匠  
這篇文章主要介紹了Java8 如何正確高效的使用并行流,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

正確使用并行流,避免共享可變狀態(tài)

錯(cuò)用并行流而產(chǎn)生錯(cuò)誤的首要原因,就是使用的算法改變了某些共享狀態(tài)。下面是另一種實(shí)現(xiàn)對前n個(gè)自然數(shù)求和的方法,但這會改變一個(gè)共享累加器:

public static long sideEffectSum(long n) {
	Accumulator accumulator = new Accumulator();
	LongStream.rangeClosed(1, n).forEach(accumulator::add);
	return accumulator.total;
}
public class Accumulator {
	public long total = 0;
	public void add(long value) { total += value; }
}

有什么問題呢?

它在本質(zhì)上就是順序的。每次訪問 total 都會出現(xiàn)數(shù)據(jù)競爭。如果用同步來修復(fù),那就完全失去并行的意義了。

為了說明這一點(diǎn),讓我們試著把 Stream 變成并行的:

public static long sideEffectParallelSum(long n) {
	Accumulator accumulator = new Accumulator();
	LongStream.rangeClosed(1, n).parallel().forEach(accumulator::add);
	return accumulator.total;
}

測試下,輸出

在這里插入圖片描述

在這里插入圖片描述

性能無關(guān)緊要了,唯一要緊的是每次執(zhí)行都會返回不同的結(jié)果,都離正確值差很遠(yuǎn)。這是由于多個(gè)線程在同時(shí)訪問累加器,執(zhí)行 total += value ,而這卻不是一個(gè)原子操作。問題的根源在于, forEach 中調(diào)用的方法有副作用它會改變多個(gè)線程共享的對象的可變狀態(tài)。

要是你想用并行 Stream 又不想引發(fā)類似的意外,就必須避免這種情況。

所以共享可變狀態(tài)會影響并行流以及并行計(jì)算,要避免共享可變狀態(tài),確保并行 Stream 得到正確的結(jié)果。

高效使用并行流

是否有必要使用并行流?

  • 如果有疑問,多次測試結(jié)果。把順序流轉(zhuǎn)成并行流輕而易舉,但卻不一定是好事
  • 留意裝箱。自動裝箱和拆箱操作會大大降低性能

Java 8中有原始類型流( IntStream 、LongStream 、 DoubleStream )來避免這種操作,但?有可能都應(yīng)該用這些流。

  • 有些操作本身在并行流上的性能就比順序流差。特別是 limit 和 findFirst 等依賴于元素順序的操作,它們在并行流上執(zhí)行的代價(jià)非常大。

例如, findAny 會比 findFirst 性能好,因?yàn)樗灰欢ㄒ错樞騺韴?zhí)行。可以調(diào)用 unordered 方法來把有序流變成無序流。那么,如果你需要流中的n個(gè)元素而不是專門要前n個(gè)的話,對無序并行流調(diào)用limit 可能會比單個(gè)有序流(比如數(shù)據(jù)源是一個(gè) List )更高效。

  • 還要考慮流的操作流水線的總計(jì)算成本。

設(shè)N是要處理的元素的總數(shù),Q是一個(gè)元素通過流水線的大致處理成本,則N*Q就是這個(gè)對成本的一個(gè)粗略的定性估計(jì)。Q值較高就意味著使用并行流時(shí)性能好的可能性比較大。

  • 對于較小的數(shù)據(jù)量,選擇并行流幾乎從來都不是一個(gè)好的決定。并行處理少數(shù)幾個(gè)元素的好處還?不上并行化造成的額外開銷
  • 要考慮流背后的數(shù)據(jù)結(jié)構(gòu)是否易于分解。

例如, ArrayList 的拆分效率比 LinkedList高得多,因?yàn)榍罢哂貌恢闅v就可以平均拆分,而后者則必須遍歷。另外,用 range 工廠方法創(chuàng)建的原始類型流也可以快速分解。

  • 流自身的特點(diǎn),以及流水線中的中間操作修改流的方式,都可能會改變分解過程的性能。

例如,一個(gè) SIZED 流可以分成大小相等的兩部分,這樣每個(gè)部分都可以比較高效地并行處理,但篩選操作可能丟棄的元素個(gè)數(shù)卻無法預(yù)測,導(dǎo)致流本身的大小未知。

  • 還要考慮終端操作中合并步驟的代價(jià)是大是?。ɡ?Collector 中的 combiner 方法)

如果這一步代價(jià)很大,那么組合每個(gè)子流產(chǎn)生的部分結(jié)果所付出的代價(jià)就可能會超出通過并行流得到的性能提升。

流的數(shù)據(jù)源和可分解性

在這里插入圖片描述

最后, 并行流背后使用的基礎(chǔ)架構(gòu)是Java 7中引入的分支/合并框架了解它的內(nèi)部原理至關(guān)重要。

java 并行計(jì)算的幾點(diǎn)實(shí)踐總結(jié)

稍微接觸了 java 的并行計(jì)算,談?wù)剮c(diǎn)淺顯的總結(jié)吧

并行計(jì)算不一定比串行計(jì)算快,一般在大規(guī)模問題才會顯示出優(yōu)勢

結(jié)合 lambda 表達(dá)式的 parallelStream 可以方便調(diào)用并行計(jì)算,但可能會出現(xiàn)空指針錯(cuò)誤,解決這一問題可能需要更高級的多線程知識

看網(wǎng)上資料,Collection 類型對并行計(jì)算支持的好,一般數(shù)組類型支持的一般。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • JAVA用遞歸實(shí)現(xiàn)全排列算法的示例代碼

    JAVA用遞歸實(shí)現(xiàn)全排列算法的示例代碼

    這篇文章主要介紹了JAVA用遞歸實(shí)現(xiàn)全排列算法的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • 詳解SpringBoot開發(fā)案例之整合定時(shí)任務(wù)(Scheduled)

    詳解SpringBoot開發(fā)案例之整合定時(shí)任務(wù)(Scheduled)

    本篇文章主要介紹了詳解SpringBoot開發(fā)案例之整合定時(shí)任務(wù)(Scheduled),具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-07-07
  • java使用jar包生成二維碼的示例代碼

    java使用jar包生成二維碼的示例代碼

    這篇文章主要介紹了java使用jar包生成二維碼的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • SpringBoot中MockMVC單元測試的實(shí)現(xiàn)

    SpringBoot中MockMVC單元測試的實(shí)現(xiàn)

    Mock是一種用于模擬和替換類的對象的方法,以便在單元測試中獨(dú)立于外部資源進(jìn)行測試,本文主要介紹了SpringBoot中MockMVC單元測試的實(shí)現(xiàn),具有應(yīng)該的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • Spring事務(wù)失效的幾種原因

    Spring事務(wù)失效的幾種原因

    在日常編碼過程中常常涉及到事務(wù),在前兩天看到一篇文章提到了Spring事務(wù),那么在此總結(jié)下在Spring環(huán)境下事務(wù)失效的幾種原因.
    2020-09-09
  • 使用SpringBoot整合Activiti6工作流的操作方法

    使用SpringBoot整合Activiti6工作流的操作方法

    這篇文章主要介紹了使用SpringBoot整合Activiti6工作流,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • 記一次集成swagger2(Knife4j)在線文檔提示:Knude4j文檔請求異常的解決辦法

    記一次集成swagger2(Knife4j)在線文檔提示:Knude4j文檔請求異常的解決辦法

    Knife4j是一個(gè)集Swagger2 和 OpenAPI3為一體的增強(qiáng)解決方案,下面這篇文章主要給大家介紹了關(guān)于一次集成swagger2(Knife4j)在線文檔提示:Knude4j文檔請求異常的解決辦法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-02-02
  • Java中并行執(zhí)行任務(wù)的多種方式

    Java中并行執(zhí)行任務(wù)的多種方式

    在Java編程中,經(jīng)常會遇到需要并行執(zhí)行任務(wù)的情況,特別是在處理大量數(shù)據(jù)或者需要異步處理的場景下,本文將介紹幾種常用的并行執(zhí)行任務(wù)的方式,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下
    2024-04-04
  • Spring Cloud Gateway組件的三種使用方式實(shí)例詳解

    Spring Cloud Gateway組件的三種使用方式實(shí)例詳解

    Spring Cloud Gateway是 Spring 官方基于 Spring5.0 、 SpringBoot2.0 和 Project Reactor 等技術(shù)開發(fā)的網(wǎng)關(guān)旨在為微服務(wù)框架提供一種簡單而有效的統(tǒng)一的API 路由管理方式,統(tǒng)一訪問接口,這篇文章主要介紹了Spring Cloud Gateway組件的三種使用方式,需要的朋友可以參考下
    2024-01-01
  • 淺談Java如何實(shí)現(xiàn)一個(gè)基于LRU時(shí)間復(fù)雜度為O(1)的緩存

    淺談Java如何實(shí)現(xiàn)一個(gè)基于LRU時(shí)間復(fù)雜度為O(1)的緩存

    這篇文章主要介紹了淺談Java如何實(shí)現(xiàn)一個(gè)基于LRU時(shí)間復(fù)雜度為O(1)的緩存,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08

最新評論

含山县| 襄垣县| 漳平市| 仁布县| 内黄县| 江永县| 岢岚县| 景谷| 明光市| 安庆市| 曲阜市| 吴川市| 壤塘县| 南乐县| 肇东市| 锡林郭勒盟| 嘉定区| 房山区| 井研县| 湘潭市| 广灵县| 天祝| 汕头市| 玉山县| 阜康市| 西峡县| 苗栗县| 汝南县| 健康| 思南县| 永康市| 安多县| 盱眙县| 康定县| 滨海县| 曲松县| 集贤县| 邮箱| 宁波市| 安岳县| 苗栗市|