使用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,它可以多線程同時讀寫,以下複製網友"拥抱心中的梦想"的文章

  • 優點

    • 資料一致性完整,為什麼?因為加鎖了,併發資料不會亂

    • 解決了像ArrayListVector這種集合多執行緒遍歷反覆運算問題,記住,Vector雖然執行緒安全,只不過是加了synchronized關鍵字,反覆運算問題完全沒有解決!

  • 適合場景

    • 讀多寫少(白名單,黑名單,商品類目的訪問和更新場景),為什麼?因為寫的時候會複製新集合

    • 集合不大,為什麼?因為寫的時候會複製新集合

    • 即時性要求不高,為什麼,因為有可能會讀取到舊的集合資料

相關心得

  • lambda中,區域變數都要求是final的,一開始我也不懂為什麼,後來查了才知道一個原因就是要防止併發時同時讀寫的錯誤
  • StringBuilderStringBuffer,這兩個偶爾會用錯,後來發明個人的記憶法就再也沒錯過了: Builder效率高(建築工)、多線程用Buffer才安全(多巴胺)

上次修改於 2022-05-25