并行流 parallel()
- 如果每次應(yīng)用函數(shù)都要依賴前一次應(yīng)用的結(jié)果,并行只會比順序處理增加開銷。
錯用并行流的首要原因,就是使用的算法改變了某些共享狀態(tài)。因為每次訪問共享狀態(tài)都會出現(xiàn)數(shù)據(jù)競爭,如果嘗試使用類似synchronize方式修復(fù),就失去并行的意義了。 - 自動裝箱和拆箱會大大降低性能,但凡有可能應(yīng)該使用原始類型流。
- 特別是limit和findFirst依賴順序的操作,本身并行性能就比順序流差。
- 單個元素的處理成本也大,元素的數(shù)量越多,并行處理的性能提高可能性越大。
- 元素的數(shù)據(jù)結(jié)構(gòu)是否容易拆分,例如ArrayList拆分效率比LinkedList高的多,因為前者可以隨機訪問拆分,后者必須遍歷拆分。
- 還要考慮collector合并combiner方法的代價,combiner代價是否會大于并行流得到的性能提升。
總結(jié):
并行化不是沒有代價的,最重要的是保證并行執(zhí)行工作的時間比在內(nèi)核之間傳輸數(shù)據(jù)的時間要長。
并行流背后的基礎(chǔ)架構(gòu)就是Java7的fork/join框架。
fork/join框架
// 使用這個框架,必須創(chuàng)建RecursiveTask的子類,R是任務(wù)返回的結(jié)果類型,如果返回時void,就是RecursiveAction類型。
public abstract class RecursiveTask<R> {
// 要實現(xiàn)的唯一抽象方法compute
protected abstract R compute();
// 例如:
@Override
public R compute() {
if (任務(wù)足夠小不可分) {
// 順序計算該任務(wù)
}
else {
// 將任務(wù)分成2個子任務(wù),遞歸調(diào)用compute拆分子任務(wù),
// 等待所有子任務(wù)完成,合并每個子任務(wù)的結(jié)果
...
}
}