ArrayList的使用及ConcurrentModificationException問題解決

weixin_34007886發表於2017-12-07

ArrayList是一種動態陣列,可以動態的增加或刪除元素。ArrayList和Vector都是用陣列實現的,但二者存在一定的區別:

  • Vector是多執行緒安全的,而ArrayList則不是
    Vector使用synchronized來實現同步,所以在效能上比不上ArrayList。

  • 當空間不足時,Vector增加原空間的一倍(預設值),但ArrayList增加原空間的50%

  • Vector可以設定增長因子,而ArrayList不可以

在日常開發中,經常使用ArrayList,可以實現快速的隨機訪問。但在多執行緒環境下,必須採用一定的措施來解決ConcurrentModificationException問題。

ConcurrentModificationException

解決方法包括3種:

  • 使用Vector代替ArrayList
    其執行緒安全的實現方式是對所有操作都加上了synchronized關鍵字,這種方式嚴重影響效率;並且也不是完全安全。具體參考Why is Java Vector class considered obsolete or deprecated?
  • 使用CopyOnWriteArrayList
    CopyOnWriteArrayList的寫操作效能較差,而多執行緒的讀操作效能較好。因為CopyOnWriteArrayList的實現方式是在寫入時通過複製連結串列來實現,每次新增都需要複製,對記憶體消耗大;在寫入時需要加synchronized保護,但讀取時則不需要進行同步。
    CopyOnWriteArrayList只能保證資料最終的一致性,但是讀寫分離時可能存在實時的不一致性。
  • 使用Collections.synchronizedList
    使用Collections.synchronizedList在部分關鍵方法中使用了synchronized進行同步;但注意在一些非原子操作時,仍需要使用synchronized。此時的鎖物件需為Collections.synchronizedList自身。
    Collections.synchronizedList的寫操作效能比CopyOnWriteArrayList在多執行緒操作的情況下要好很多,而讀操作因為是採用了synchronized關鍵字的方式,其讀操作效能並不如CopyOnWriteArrayList。

可以根據不同的應用場景,選擇不同的多執行緒安全實現類。

參考方法:
CopyOnWriteArrayList與Collections.synchronizedList的效能對比
聊聊併發-Java中的Copy-On-Write容器
【集合型別的併發】Collections.synchronizedList

相關文章