使用parallelStream要注意的坑
一些多線程沒親自踩過真的不知道
CopyOnWriteArrayList
- 場景是這樣,我有一個查詢"播放計畫"列表的功能,一個計劃關聯到多個節目與裝置,所以在buildPlayPlanVo這邊我為了加速就想用分治的辦法去做
List<PlayPlanVo> result = new CopyOnWriteArrayList<>();
// 獲取與播放計畫關聯的節目與裝置,封裝成Vo
planList.parallelStream().forEach(playPlan -> {
try {
result.add(buildPlayPlanVo(playPlan));
} catch (IOException e) {
...
}
});
result.sort(Comparator.comparing(PlayPlanVo::getId));
return result;
-
最一開始用了
ArrayList
,結果就報錯(例如sort的時候是null),顯然我忘記ArrayList
是併發不安全的。所以換成CopyOnWriteArrayList
,它可以多線程同時讀寫,以下複製網友"拥抱心中的梦想"的文章 -
優點
-
資料一致性完整,為什麼?因為加鎖了,併發資料不會亂
-
解決了像
ArrayList
、Vector
這種集合多執行緒遍歷反覆運算問題,記住,Vector
雖然執行緒安全,只不過是加了synchronized
關鍵字,反覆運算問題完全沒有解決!
-
-
適合場景
-
讀多寫少(白名單,黑名單,商品類目的訪問和更新場景),為什麼?因為寫的時候會複製新集合
-
集合不大,為什麼?因為寫的時候會複製新集合
-
即時性要求不高,為什麼,因為有可能會讀取到舊的集合資料
-
相關心得
- 在
lambda
中,區域變數都要求是final
的,一開始我也不懂為什麼,後來查了才知道一個原因就是要防止併發時同時讀寫的錯誤 StringBuilder
跟StringBuffer
,這兩個偶爾會用錯,後來發明個人的記憶法就再也沒錯過了: Builder效率高(建築工
)、多線程用Buffer才安全(多巴胺
)
上次修改於 2022-05-25