學(xué)習(xí)札記-Java8系列-11-并行流

學(xué)習(xí)札記-Java8系列-11-并行流

并發(fā)和并行

●并發(fā)和并行

并發(fā)是多個(gè)任務(wù)共享時(shí)間段(由CPU切換執(zhí)行磁餐,就像是在同時(shí)執(zhí)行)

并行是多個(gè)任務(wù)發(fā)生在同一時(shí)刻(真真正正的同時(shí)執(zhí)行)(必須在多核CPU下)

并行就像用更多的馬車(CPU)來拉貨(執(zhí)行任務(wù)),貨物總量(任務(wù)量)一定裕偿,那么花費(fèi)的時(shí)間自然減少了。

所以并行可以縮短任務(wù)執(zhí)行時(shí)間痛单,提高多核CPU的利用率


image.png

●數(shù)據(jù)并行化

任務(wù)可以并行化執(zhí)行嘿棘,同樣的數(shù)據(jù)也可以并行化處理!

數(shù)據(jù)并行化是指將數(shù)據(jù)分成塊旭绒,為每塊數(shù)據(jù)分配單獨(dú)的處理單元鸟妙。也就是并行流

如何使數(shù)據(jù)并行化

在Java8之前焦人,當(dāng)需要對存在于集合或數(shù)組中的若干元素進(jìn)行并發(fā)操作時(shí),簡直就是噩夢重父!我們需要仔細(xì)考慮多線程環(huán)境下的原子性花椭、競爭甚至鎖問題。

使用Java5的java.util.concurrent.*并發(fā)庫也還是要考慮諸多細(xì)節(jié)必須十分謹(jǐn)慎房午,

使用Java7的fork/join框架編碼和調(diào)試對于一般程序員來說難度還是太大

而這一切對于Java8中的Stream矿辽,不過是小菜一碟!直接調(diào)用API方法就可以搞定郭厌!

(Stream API 可以聲明性地通過parallel() 與sequential() 在并行流與順序流之間進(jìn)行切換)

轉(zhuǎn)換為并行流

Stream 的父接口java.util.stream.BaseStream 中定義了一個(gè)parallel 方法:

只需要在流上調(diào)用一下無參數(shù)的parallel 方法袋倔,那么當(dāng)前流即可變身成為支持并發(fā)操作的流,返回值仍然為

Stream 類型折柠。例如:

Stream<Integer> stream = Stream.*of*(10, 20, 30, 40, 50).parallel();

直接獲取并行流

在通過集合獲取流時(shí)宾娜,也可以直接調(diào)用parallelStream 方法來直接獲取支持并發(fā)操作的流。

代碼為:

Stream<String> stream= **new** ArrayList<String>().parallelStream();

使用并行流

并行流后續(xù)操作的使用方式還是和以前一樣扇售,只是底層執(zhí)行的時(shí)候會(huì)使用多CPU并行執(zhí)行

比如多次執(zhí)行下面這段代碼前塔,并行流的輸出順序在很大概率上是不一定的:

@Test
public void test1() throws Exception {
    System.out.println("=======================順序流=========================");
    Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).forEach(System.out::println);
    System.out.println("=======================并行流=========================");
    Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).parallel().forEach(System.out::println);
}

效率對比

需求:使用普通for和Stream和Parallel Stream 分別計(jì)算累加和并統(tǒng)計(jì)執(zhí)行效率

public class ParallelStream {
    // 需求:使用普通for和Stream和Parallel Stream 分別計(jì)算累加和并統(tǒng)計(jì)執(zhí)行效率
    @Test//35592ms
    public void testFor() throws Exception {
        long start = System.currentTimeMillis();
        long sum = 0;
        for (long i = 0; i < 100000000000L; i++) {
            sum += i;
        }
        System.out.println(sum);
        long end = System.currentTimeMillis();
        System.out.println(end-start);
    }
    @Test//52974ms
    public void testStream() throws Exception {
        long start = System.currentTimeMillis();
        long sum = LongStream.rangeClosed(0, 100000000000L).sum();
        System.out.println(sum);
        long end = System.currentTimeMillis();
        System.out.println(end-start);
    }
    @Test//12808ms
    public void testParallelStream() throws Exception {
        long start = System.currentTimeMillis();
        long sum = LongStream.rangeClosed(0, 100000000000L).parallel().sum();
        System.out.println(sum);
        long end = System.currentTimeMillis();
        System.out.println(end-start);
    }
}

并行流的性能

影響并行流性能的主要因素

●數(shù)據(jù)大小

輸入數(shù)據(jù)的大小會(huì)影響并行化處理對性能的提升。將問題分解之后并行化處理承冰,再將結(jié)果合并會(huì)帶來額外的開銷华弓。因此只有數(shù)據(jù)足夠大、每個(gè)數(shù)據(jù)處理管道花費(fèi)的時(shí)間足夠多時(shí)困乒,并行化處理才有意義该抒。

●源數(shù)據(jù)結(jié)構(gòu)

每個(gè)管道的操作都基于一些初始數(shù)據(jù)源,通常是集合顶燕。將不同的數(shù)據(jù)源分割相對容易,這里的開銷影響了在管道中并行處理數(shù)據(jù)時(shí)到底能帶來多少性能上的提升冈爹。

●裝箱

處理基本類型比處理裝箱類型要快涌攻。

●核的數(shù)量

極端情況下,只有一個(gè)核频伤,因此完全沒必要并行化恳谎。顯然,擁有的核越多憋肖,獲得潛在性能提升的幅度就越大因痛。在實(shí)踐中,核的數(shù)量不單指你的機(jī)器上有多少核岸更,更是指運(yùn)行時(shí)你的機(jī)器能使用多少核鸵膏。這也就是說同時(shí)運(yùn)行的其他進(jìn)程,或者線程關(guān)聯(lián)性(強(qiáng)制線程在某些核或CPU 上運(yùn)行)會(huì)影響性能怎炊。

●單元處理開銷

比如數(shù)據(jù)大小谭企,這是一場并行執(zhí)行花費(fèi)時(shí)間和分解合并操作開銷之間的戰(zhàn)爭廓译。花在流中每個(gè)元素身上的時(shí)間越長债查,并行操作帶來的性能提升越明顯非区。

注意:

在底層,并行流還是沿用了fork/join 框架盹廷。fork 遞歸式地分解問題征绸,然后每段并行執(zhí)行,最終由join 合并結(jié)果俄占,返回最后的值管怠。

根據(jù)性能的好壞,將核心類庫提供的通用數(shù)據(jù)結(jié)構(gòu)分成以下3 組

●性能好

ArrayList颠放、數(shù)組或IntStream.range排惨,這些數(shù)據(jù)結(jié)構(gòu)支持隨機(jī)讀取,也就是說它們能輕而易舉地被任意分解碰凶。

●性能一般

HashSet暮芭、TreeSet,這些數(shù)據(jù)結(jié)構(gòu)不易公平地被分解欲低,但是大多數(shù)時(shí)候分解是可能的辕宏。

●性能差

有些數(shù)據(jù)結(jié)構(gòu)難于分解,比如砾莱,可能要花O(N) 的時(shí)間復(fù)雜度來分解問題瑞筐。其中包括LinkedList,對半分解太難了腊瑟。還有Streams.iterate 和BufferedReader.lines聚假,它們長度未知,因此很難預(yù)測該在哪里分解闰非。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末膘格,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子财松,更是在濱河造成了極大的恐慌瘪贱,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辆毡,死亡現(xiàn)場離奇詭異菜秦,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)舶掖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門球昨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人访锻,你說我怎么就攤上這事褪尝∧只瘢” “怎么了?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵河哑,是天一觀的道長避诽。 經(jīng)常有香客問我,道長璃谨,這世上最難降的妖魔是什么沙庐? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮佳吞,結(jié)果婚禮上拱雏,老公的妹妹穿的比我還像新娘。我一直安慰自己底扳,他們只是感情好铸抑,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著衷模,像睡著了一般鹊汛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上阱冶,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天刁憋,我揣著相機(jī)與錄音,去河邊找鬼木蹬。 笑死至耻,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的镊叁。 我是一名探鬼主播尘颓,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼晦譬!你這毒婦竟也來了泥耀?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蛔添,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后兜辞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體迎瞧,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年逸吵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了凶硅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,567評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡扫皱,死狀恐怖足绅,靈堂內(nèi)的尸體忽然破棺而出捷绑,到底是詐尸還是另有隱情,我是刑警寧澤氢妈,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布粹污,位于F島的核電站,受9級(jí)特大地震影響首量,放射性物質(zhì)發(fā)生泄漏壮吩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一加缘、第九天 我趴在偏房一處隱蔽的房頂上張望鸭叙。 院中可真熱鬧,春花似錦拣宏、人聲如沸沈贝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宋下。三九已至,卻和暖如春市俊,著一層夾襖步出監(jiān)牢的瞬間杨凑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工摆昧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留撩满,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓绅你,卻偏偏與公主長得像伺帘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子忌锯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內(nèi)容