Java 8新特性之 並行和並行數組(八惡人-8)
Jody Domingre 多莫歌·喬迪
“How you doing, dummy?” 你還好嗎,傻瓜
一、基本介紹
Java8不僅增加了Stream,而且還增加了parallelStream(並行流)。除並行流外,對於普通數組,Java8提供了也簡單的並行功能。數組排序,一般使用Arrays.sort()方法串行排序,Java8新增方法Arrays.parallelSort()並行排序。
二、使用
1、parallelSort()
Java 8新增加了很多方法支持並行的數組處理。最重要的大概是parallelSort()這個方法顯著地使排序在多核計算機上速度加快。下面的小例子演示了這個新的方法(parallelXXX
這一小段代碼使用parallelSetAll() t方法填充這個長度是2000的數組,然後使用parallelSort() 排序。這個程序輸出了排序前和排序後的10個數字來驗證數組真的已經被排序了。示例可能的輸出如下(請註意這些數字是隨機產生的)
import java.util.Arrays; import java.util.concurrent.ThreadLocalRandom; public class ParallelArrays { public static void main( String[] args ) { long[] arrayOfLong = new long [ 20000 ]; Arrays.parallelSetAll( arrayOfLong, index -> ThreadLocalRandom.current().nextInt( 1000000 ) ); Arrays.stream( arrayOfLong ).limit( 10 ).forEach( i -> System.out.print( i + " " ) ); System.out.println(); Arrays.parallelSort( arrayOfLong ); Arrays.stream( arrayOfLong ).limit( 10 ).forEach( i -> System.out.print( i + " " ) ); System.out.println(); } }
2、並行流使用
Map<Boolean, List<Integer>> groupByPrimary = numbers //根據特定的條件(比如:素數和非素數)對數組進行分組
.parallelStream().collect(Collectors.groupingBy(s -> Utility.isPrime(s)));
Integer[] prims = numbers.parallelStream().filter(s -> Utility.isPrime(s)) //對數組進行過濾
.toArray();
三、性能測試
它的性能如何?
為了測試這些並行操作API的性能, 我在兩種情況(低競爭和高競爭)下進行了實驗。原因是單獨運行一個多核算法,往往會有好的性能,但在真實的服務器環境中運行,情況就完全不同了。真實環境中往往有大量的線程在競爭寶貴的CPU時間片以處理消息或用戶請求,由於競爭的存在,程序的性能就降低了。所以我進行了接下來的測試。我首先隨機生成了長度為100K的整數數組,這些整數的取值在0到1百萬之間。然後我分別使用傳統的順序方法和新的Java 8的並行API對這個數組進行了排序,分組和過濾。結果並不使人驚訝。
- 快速排序快了4.7倍
- 分組快了5倍
- 過濾快了5.5倍
這可以說明java 8的並行API具有非常好的性能嗎?很不幸,不能。
*測試結果與運行了100次的附加測試結果一致。
*測試機器為MBP,i7四核。
在有負載的情況下會發生什麽呢?
目前為止新API的性能表現非常出色,原因是線程之間對CPU的時間片的競爭非常少。這是理想的環境,但不行的是,理想環境往往不會出現在現實環境中。為了模擬真實的環境,我建立了第二個測試。這次測試使用跟第一次相同的算法,但測試任務在十個並發線程上執行,以模擬處在壓力環境中的服務器同時處理十個請求的情況。這十個請求使用傳統的順利處理方法或Java 8的新API處理。
測試結果
- 排序現在只快了20%
- 過濾現在只快了20%
- 分組現在滿了15%
更高的規模和競爭水平很可能使這些數字進一步下降。原因是在一個多線程的環境中添加線程並不一定能幫助你提高計算效率,是計算機的CPU個數決定了計算效率,而不是線程個數。
結論
雖然這些都是非常強大和易於使用的API,但它們不是銀彈。我們仍然需要花費精力去判斷何時應該使用它們。如果你事先知道你會做多個處理並行操作,那麽考慮使用排隊架構,並使並發操作數和你的處理器數量相匹配可能是一個好主意。這裏的難點在於運行時性能將依賴於實際的硬件體系結構和服務器所處的壓力情況。你可能只有在壓力測試或者生產環境中才能看到代碼的運行時性能,使之成為一個“易編碼,難調試”的經典案例。
參考鏈接:
http://www.importnew.com/11113.html
圖片來源:八惡人(movie)
Java 8新特性之 並行和並行數組(八惡人-8)