Java8新特性系列(流性能)

題圖:by pixel2013 From pixabay

上期介紹了Java8中Stream的新特性翅雏,本期我們將測(cè)試下streamparallelStream的性能以及應(yīng)用的場(chǎng)景。

先上代碼

public class StreamTest {

    private static final int MAX_INT = 1_000_000;

    public static void stream() {
        List<String> list = new ArrayList<>();
        IntStream.range(0, MAX_INT).forEach(value -> {
            UUID uuid = UUID.randomUUID();
            list.add(uuid.toString());
        });

        long startTime = System.nanoTime();

        list.stream().sorted().collect(Collectors.toList());

        long endTime = System.nanoTime();
        long durationTime = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
        System.out.println("stream execute time : " + durationTime);
    }

    public static void parallelStream() {
        List<String> list = new ArrayList<>();
        IntStream.range(0, MAX_INT).forEach(value -> {
            UUID uuid = UUID.randomUUID();
            list.add(uuid.toString());
        });

        long startTime = System.nanoTime();

        list.parallelStream().sorted().collect(Collectors.toList());

        long endTime = System.nanoTime();
        long durationTime = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
        System.out.println("parallelStream execute time : " + durationTime);
    }

    public static void main(String[] args) {
        stream();
        parallelStream();
    }
}

MAX_INT = 1_000_000; //Jav8中數(shù)字可以用_間隔人芽,類似1,000,000

Max_INT為1時(shí)望几,結(jié)果為:
stream execute time : 6
parallelStream execute time : 8

Max_INT為100時(shí),結(jié)果為:
stream execute time : 7
parallelStream execute time : 7

Max_INT為1_000時(shí)萤厅,結(jié)果為:
stream execute time : 15
parallelStream execute time : 22

Max_INT為10_000時(shí)橄抹,結(jié)果為:
stream execute time : 28
parallelStream execute time : 21

Max_INT為100_000時(shí)靴迫,結(jié)果為:
stream execute time : 98
parallelStream execute time : 62

Max_INT為1_000_000時(shí),結(jié)果為:
stream execute time : 742
parallelStream execute time : 429

Max_INT為5_000_000時(shí)楼誓,結(jié)果為:
stream execute time : 4299
parallelStream execute time : 2191

Max_INT為10_000_000時(shí)玉锌,結(jié)果為:
stream execute time : 9849
parallelStream execute time : 6923

分析

并行適用的場(chǎng)景?

  • 有大量的元素要處理
  • 性能問題是首要考慮的
  • 沒有在一個(gè)多線程的環(huán)境中

所以如Java Web應(yīng)用疟羹,底層都是Servlet主守,我們知道,Servlet是多線程的榄融,所以在web應(yīng)用中并行流并不適用参淫,而對(duì)于數(shù)據(jù)的處理、算法的驗(yàn)證等單線程環(huán)境是適用的愧杯。

原理

并行流底層其實(shí)是ForkJoinPool 涎才,用的是分治法,即Fork/Join方法

當(dāng)執(zhí)行新的任務(wù)時(shí)它可以將其拆分分成更小的任務(wù)執(zhí)行力九,并將小任務(wù)加到線 程隊(duì)列中耍铜,然后再?gòu)囊粋€(gè)隨機(jī)線程的隊(duì)列中偷一個(gè)并把它放在自己的隊(duì)列中。

相對(duì)于一般的線程池實(shí)現(xiàn)跌前,fork/join框架的優(yōu)勢(shì)體現(xiàn)在對(duì)其中包含的任務(wù)的處理方式上业扒,在一般的線程池中,如果一個(gè)線程正在執(zhí)行的任務(wù)由于某些原因無法繼續(xù)運(yùn)行,那么該線程會(huì)處于等待狀態(tài)舒萎。而在fork/join框架實(shí)現(xiàn)中,如果某個(gè)子問題由于等待另外一個(gè)子問題的完成而無法繼續(xù)運(yùn)行.那么處理該子問題的線程會(huì)主動(dòng)尋找其他尚未運(yùn)行的子問題來執(zhí)行蹭沛。這種方式減少了線程的等待時(shí)間臂寝,提高了性能。

public static void main(String[] args) {
    ForkJoinPool pool = ForkJoinPool.commonPool();
    System.out.println(pool.getParallelism());
}

結(jié)果:
3

我們可以通過參數(shù)來修改:

WX20171230-125634@2x.png

結(jié)果:
10

總結(jié)

如何高效使用并行流摊灭?

  • 如果用循環(huán)還是順序流或者是并行流咆贬,像我們上面那樣測(cè)試一下;
  • 注意裝箱帚呼,盡量使用IntStream, LongStream掏缎,和DoubleStream來避免裝箱拆箱;
  • 有些操作在并行流上性能很差,比如limit煤杀,findFirst等依賴順序的操作眷蜈。unordered方法可以把有序流轉(zhuǎn)為無序流,使用findAny等好很多沈自,在無序流上用limit也好很多;
  • 計(jì)算流水線操作總成本酌儒,處理單個(gè)元素用時(shí)越多,并行就越劃算枯途;
  • 對(duì)于較小的數(shù)據(jù)量忌怎,用并行不一定是好事兒籍滴;
  • 區(qū)分單線程和多線程,多線程下并行不一定是好事兒榴啸;
  • 數(shù)據(jù)結(jié)果是否易于分解孽惰,比如ArrayListLinkedList易于分解,range創(chuàng)建的原始流也易于分解鸥印;
  • 終端操作中的合并大家是否很大勋功,大了也不劃算。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末辅甥,一起剝皮案震驚了整個(gè)濱河市酝润,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌璃弄,老刑警劉巖要销,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異夏块,居然都是意外死亡疏咐,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門脐供,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浑塞,“玉大人,你說我怎么就攤上這事政己∽煤荆” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵歇由,是天一觀的道長(zhǎng)卵牍。 經(jīng)常有香客問我,道長(zhǎng)沦泌,這世上最難降的妖魔是什么糊昙? 我笑而不...
    開封第一講書人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮谢谦,結(jié)果婚禮上释牺,老公的妹妹穿的比我還像新娘。我一直安慰自己回挽,他們只是感情好没咙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著千劈,像睡著了一般镜撩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評(píng)論 1 290
  • 那天袁梗,我揣著相機(jī)與錄音宜鸯,去河邊找鬼。 笑死遮怜,一個(gè)胖子當(dāng)著我的面吹牛淋袖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锯梁,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼即碗,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了陌凳?” 一聲冷哼從身側(cè)響起剥懒,我...
    開封第一講書人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎合敦,沒想到半個(gè)月后初橘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡充岛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年保檐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片崔梗。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡夜只,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蒜魄,到底是詐尸還是另有隱情扔亥,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布谈为,位于F島的核電站砸王,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏峦阁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一耘成、第九天 我趴在偏房一處隱蔽的房頂上張望榔昔。 院中可真熱鬧,春花似錦瘪菌、人聲如沸撒会。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)诵肛。三九已至,卻和暖如春默穴,著一層夾襖步出監(jiān)牢的瞬間怔檩,已是汗流浹背褪秀。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留薛训,地道東北人媒吗。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像乙埃,于是被迫代替她去往敵國(guó)和親闸英。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348