自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

你破壞Java代碼的樣子,真美!

開(kāi)發(fā) 后端
在之前如果需要處理集合需要先手動(dòng)分成幾部分,然后為每部分創(chuàng)建線程,最后在合適的時(shí)候合并,這是手動(dòng)處理并行集合的方法,在java8中,有了新功能,可以一下開(kāi)啟并行模式。

[[357949]]

本文轉(zhuǎn)載自微信公眾號(hào)「小明菜市場(chǎng)」,作者小明菜市場(chǎng)。轉(zhuǎn)載本文請(qǐng)聯(lián)系小明菜市場(chǎng)公眾號(hào)。

前言

在之前如果需要處理集合需要先手動(dòng)分成幾部分,然后為每部分創(chuàng)建線程,最后在合適的時(shí)候合并,這是手動(dòng)處理并行集合的方法,在java8中,有了新功能,可以一下開(kāi)啟并行模式。

并行流

認(rèn)識(shí)開(kāi)啟并行流

并行流是什么?是把一個(gè)流內(nèi)容分成多個(gè)數(shù)據(jù)塊,并用不同線程分別處理每個(gè)不同數(shù)據(jù)塊的流。例如,有下面一個(gè)例子,在List中,需要對(duì)List數(shù)據(jù)進(jìn)行分別計(jì)算,其代碼如下所示:

  1. List<Apple> appleList = new ArrayList<>(); // 假裝數(shù)據(jù)是從庫(kù)里查出來(lái)的 
  2.  
  3. for (Apple apple : appleList) { 
  4.     apple.setPrice(5.0 * apple.getWeight() / 1000); 

在這里,時(shí)間復(fù)雜度為O(list.size),隨著list的增加,耗時(shí)也在增加。并行流可以解決這個(gè)問(wèn)題,代碼如下所示:

appleList.parallelStream().forEach(apple -> apple.setPrice(5.0 * apple.getWeight() / 1000));

這里通過(guò)調(diào)parallelStream()說(shuō)明當(dāng)前流為并行流,然后進(jìn)行并行執(zhí)行。并行流內(nèi)部使用了默認(rèn)的ForkJoinPool線程池,默認(rèn)線程數(shù)為處理器的核心數(shù)。

測(cè)試并行流

普通代碼如下所示:

  1. public static void main(String[] args) throws InterruptedException { 
  2.     List<Apple> appleList = initAppleList(); 
  3.  
  4.     Date begin = new Date(); 
  5.     for (Apple apple : appleList) { 
  6.         apple.setPrice(5.0 * apple.getWeight() / 1000); 
  7.         Thread.sleep(1000); 
  8.     } 
  9.     Date end = new Date(); 
  10.     log.info("蘋(píng)果數(shù)量:{}個(gè), 耗時(shí):{}s", appleList.size(), (end.getTime() - begin.getTime()) /1000); 

輸出的內(nèi)容為耗時(shí)4s。

并行代碼如下所示:

  1. List<Apple> appleList = initAppleList(); 
  2.  
  3. Date begin = new Date(); 
  4. appleList.parallelStream().forEach(apple -> 
  5.                                    { 
  6.                                        apple.setPrice(5.0 * apple.getWeight() / 1000); 
  7.                                        try { 
  8.                                            Thread.sleep(1000); 
  9.                                        } catch (InterruptedException e) { 
  10.                                            e.printStackTrace(); 
  11.                                        } 
  12.                                    } 
  13.                                   ); 
  14. Date end = new Date(); 
  15. log.info("蘋(píng)果數(shù)量:{}個(gè), 耗時(shí):{}s", appleList.size(), (end.getTime() - begin.getTime()) /1000); 

輸出結(jié)果為耗時(shí)1s。可以看到耗時(shí)大大提升了3s。

并行流拆分會(huì)影響流的速度

對(duì)于并行流來(lái)說(shuō)需要注意以下幾點(diǎn):

  1. 對(duì)于 iterate 方法來(lái)處理的前 n 個(gè)數(shù)字來(lái)說(shuō),不管并行與否,它總是慢于循環(huán)的,
  2. 而對(duì)于 LongStream.rangeClosed() 方法來(lái)說(shuō),就不存在 iterate 的第兩個(gè)痛點(diǎn)了。它生成的是基本類型的值,不用拆裝箱操作,另外它可以直接將要生成的數(shù)字 1 - n 拆分成 1 - n/4, 1n/4 - 2n/4, ... 3n/4 - n 這樣四部分。因此并行狀態(tài)下的 rangeClosed() 是快于 for 循環(huán)外部迭代的

代碼如下所示:

  1. package lambdasinaction.chap7; 
  2.  
  3. import java.util.stream.*; 
  4.  
  5. public class ParallelStreams { 
  6.  
  7.     public static long iterativeSum(long n) { 
  8.         long result = 0; 
  9.         for (long i = 0; i <= n; i++) { 
  10.             result += i; 
  11.         } 
  12.         return result; 
  13.     } 
  14.  
  15.     public static long sequentialSum(long n) { 
  16.         return Stream.iterate(1L, i -> i + 1).limit(n).reduce(Long::sum).get(); 
  17.     } 
  18.  
  19.     public static long parallelSum(long n) { 
  20.         return Stream.iterate(1L, i -> i + 1).limit(n).parallel().reduce(Long::sum).get(); 
  21.     } 
  22.  
  23.     public static long rangedSum(long n) { 
  24.         return LongStream.rangeClosed(1, n).reduce(Long::sum).getAsLong(); 
  25.     } 
  26.  
  27.     public static long parallelRangedSum(long n) { 
  28.         return LongStream.rangeClosed(1, n).parallel().reduce(Long::sum).getAsLong(); 
  29.     } 
  30.  
  31. package lambdasinaction.chap7; 
  32.  
  33. import java.util.concurrent.*; 
  34. import java.util.function.*; 
  35.  
  36. public class ParallelStreamsHarness { 
  37.  
  38.     public static final ForkJoinPool FORK_JOIN_POOL = new ForkJoinPool(); 
  39.  
  40.     public static void main(String[] args) { 
  41.         System.out.println("Iterative Sum done in: " + measurePerf(ParallelStreams::iterativeSum, 10_000_000L) + " msecs"); 
  42.         System.out.println("Sequential Sum done in: " + measurePerf(ParallelStreams::sequentialSum, 10_000_000L) + " msecs"); 
  43.         System.out.println("Parallel forkJoinSum done in: " + measurePerf(ParallelStreams::parallelSum, 10_000_000L) + " msecs" ); 
  44.         System.out.println("Range forkJoinSum done in: " + measurePerf(ParallelStreams::rangedSum, 10_000_000L) + " msecs"); 
  45.         System.out.println("Parallel range forkJoinSum done in: " + measurePerf(ParallelStreams::parallelRangedSum, 10_000_000L) + " msecs" ); 
  46.     } 
  47.  
  48.     public static <T, R> long measurePerf(Function<T, R> f, T input) { 
  49.         long fastest = Long.MAX_VALUE; 
  50.         for (int i = 0; i < 10; i++) { 
  51.             long start = System.nanoTime(); 
  52.             R result = f.apply(input); 
  53.             long duration = (System.nanoTime() - start) / 1_000_000; 
  54.             System.out.println("Result: " + result); 
  55.             if (duration < fastest) fastest = duration; 
  56.         } 
  57.         return fastest; 
  58.     } 

共享變量會(huì)造成數(shù)據(jù)出現(xiàn)問(wèn)題

  1. public static long sideEffectSum(long n) { 
  2.     Accumulator accumulator = new Accumulator(); 
  3.     LongStream.rangeClosed(1, n).forEach(accumulator::add); 
  4.     return accumulator.total; 
  5.  
  6. public static long sideEffectParallelSum(long n) { 
  7.     Accumulator accumulator = new Accumulator(); 
  8.     LongStream.rangeClosed(1, n).parallel().forEach(accumulator::add); 
  9.     return accumulator.total; 
  10.  
  11. public static class Accumulator { 
  12.     private long total = 0; 
  13.  
  14.     public void add(long value) { 
  15.         total += value; 
  16.     } 

并行流的注意

  1. 盡量使用 LongStream / IntStream / DoubleStream 等原始數(shù)據(jù)流代替 Stream 來(lái)處理數(shù)字,以避免頻繁拆裝箱帶來(lái)的額外開(kāi)銷
  2. 要考慮流的操作流水線的總計(jì)算成本,假設(shè) N 是要操作的任務(wù)總數(shù),Q 是每次操作的時(shí)間。N * Q 就是操作的總時(shí)間,Q 值越大就意味著使用并行流帶來(lái)收益的可能性越大
  3. 對(duì)于較少的數(shù)據(jù)量,不建議使用并行流
  4. 容易拆分成塊的流數(shù)據(jù),建議使用并行流

 

 

責(zé)任編輯:武曉燕 來(lái)源: 小明菜市場(chǎng)
相關(guān)推薦

2015-06-25 10:00:30

Java 8代碼

2020-09-18 07:05:34

Java編程語(yǔ)言

2021-03-12 11:50:08

項(xiàng)目組件 API

2020-11-04 11:17:20

好代碼程序員整潔

2012-07-04 17:11:28

微軟操作系統(tǒng)

2019-11-24 19:25:17

網(wǎng)絡(luò)安全邊緣計(jì)算攻擊

2013-10-28 13:30:21

Windows 9微軟

2013-12-16 13:58:55

Win9Windows 9概念圖

2023-07-27 10:24:54

數(shù)字化轉(zhuǎn)型NetOps

2022-06-01 11:14:42

Java代碼技巧

2018-07-10 09:00:00

Linuxdd工具磁盤

2021-05-27 09:30:51

Java流程控制

2021-02-21 11:52:41

云計(jì)算

2011-09-26 11:22:10

2011-09-02 17:52:56

ubuntuLinuxGNOME

2021-10-29 10:55:07

Go 泛型語(yǔ)言

2020-07-14 14:50:44

Vue代碼前端

2020-07-15 07:57:17

代碼Vue開(kāi)發(fā)

2020-08-21 07:57:13

軟件開(kāi)發(fā)程序員

2013-03-25 09:41:20

PythonCython
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)