前言
java8除了新增stream,還提供了parallel stream-多線程版的stream,parallel stream的優勢是:充分利用多線程,提高程序運行效率,但是正確的使用並不簡單,盲目使用可能導致以下后果
- 效率不增反降
- 增加額外的復雜度,程序更易出錯
- 運行結果不正確
效率不增反降
parallel stream是基於fork/join框架的,簡單點說就是使用多線程來完成的,使用parallel stream時要考慮初始化fork/join框架的時間,如果要執行的任務很簡單,那么初始化fork/join框架的時間會遠多於執行任務所需時間,也就導致了效率的降低.
根據附錄doug Lee的說明,任務數量*執行方法的行數>=10000或者執行的是消耗大量時間操作(如io/數據庫)才有必要使用
增加額外的復雜度,程序更易出錯
在spring框架中,假設有一組主鍵id,使用這組id去數據庫獲取記錄
//DB.fetchRecord(long id)使用當前線程session連接數據庫
ids.parallelStream().map(DB::fetchRecord).collect(Collections.toList());
這里使用parallel stream是正確的,但是運行會報錯,類似於 can't obtain session from current thread.原因就是多線程運行,對應的線程沒有綁定的session,要完成上面的功能需要提供一個特殊版本的DB方法
//不從線程獲取session,而是在方法內部開啟新的session
DB.fetchRecordWithoutSession(long id)
運行結果不正確
還是以上面的例子,session問題已經解決,如果獲取到的記錄需要和ids順序相同,那么使用parallel獲取到的結果就是不正確的,原因還是多線程
如何正確使用:
- 確保要執行的任務對線程環境沒有依賴
- 任務消耗時間長/數據量大到不用思考是否要用parallel
- 結果沒有順序要求