並行編程勢不可擋,Java從1.7開始就提供了Fork/Join 支持並行處理。java1.8 進一步增強。html
並行處理就是將任務拆分子任務,分發給多個處理器同時處理,以後合併。java
Java 8 引入了許多特性,Stream API是其中重要的一部分。區別 InputStream OutputStream,Stream API 是處理對象流而不是字節流。git
執行原理以下,流分串行和並行兩種執行方式github
// 串行執行流 stream().filter(e -> e > 10).count(); // 並行執行流 .parallelStream().filter(e -> e > 10).count()
並行執行時,java將流劃分爲多個子流,分散在不一樣CPU並行處理,而後進行合併。編程
並行必定比串行更快嗎?這不必定,取決於兩方面條件:網絡
使用並行流時,不要使用collectors.groupingBy,collectors.toMap,替代爲oracle
collectors.groupingByConcurrent , collectors.toConcurrentMap,或直接使用串行流。學習
緣由,並行流執行時,經過操做Key來合併多個map的操做比較昂貴。詳細你們能夠查看官網介紹。this
https://docs.oracle.com/javas...
Map<String, List<Person>> byGender = roster .stream() .collect(Collectors.groupingBy(Person::getGender)); ConcurrentMap<String, List<Person>> byGender = roster .parallelStream() .collect(Collectors.groupingByConcurrent(Person::getGender));
ParallelStreams 默認使用 ForkJoinPool.commonPool()線程池。spa
注意:默認狀況下,你寫的 ParallelStreams 都是經過該線程池調度執行,整個應用程序都共享這個線程池。
看一個例子,咱們查詢一批新聞數據,能夠利用並行化來處理遠程新聞下載。
public List<News> queryNews(Stream<String> ids) { return ids.parallel() .map(this::getNews) // 網絡操做,新聞下載 .collect(toList()); }
由於是網絡操做,存在不少不肯定性,假如某個任務運行時間較長,致使線程池資源佔據,阻塞其它線程,這樣就阻止了其餘的並行流任務正常進行。
若是解決這個問題的其中一種方式,進行線程池隔離。那麼如何自定義並行流的線程池呢?
ForkJoinPool 構造參數咱們默認設置爲CPU核心數。
ForkJoinPool customThreadPool = new ForkJoinPool(4); long actualTotal = customThreadPool .submit(() -> roster.parallelStream().reduce(0, Integer::sum)).get();
針對 Stream API 一些侷限性,Github上有個開源庫作了補充。
https://github.com/pivovarit/...
Java 1.8 提供的Stream API簡化了代碼,很好用。不過在使用過程當中應該注意以上問題。
歡迎你們留言交流,一塊兒學習分享!!!