Java多線程併發之同步容器和併發容器-第一篇

Java多線程併發之同步容器和併發容器-第一篇

概述

本文主要講解在Java多線程併發開發中,集合中有哪些支持併發的的。什麼是同步容器(集合),什麼是併發容器(集合)?併發容器分類有哪些?每個分類都有哪些類?

本文是《凱哥分享Java併發編程之J.U.C包講解》系列教程中的第五篇。如果想系統學習,凱哥(kaigejava)建議從第一篇開始看。

從本篇開始,我們就來講解講解Java的併發容器。大致思路:先介紹什麼是併發容器。然後講解list相關的、map相關的以及隊列相關的。這個系列會有好幾篇文章。大家最好跟著一篇一篇學。

正文開始

回顧Java中常用的容器(集合):

我們知道Java內部的容器類是集合相關的。主要包括:List接口、Map接口以及Set接口及其子類。

Collection及Map體系如下圖:

Java多線程併發之同步容器和併發容器-第一篇

我們常用的類關係簡化版:

Java多線程併發之同步容器和併發容器-第一篇

上圖中少了一個類:Properties.這個類用的比較少。

Java多線程併發之同步容器和併發容器-第一篇

我們來簡單複習下Java中集合子類及數據結構:

頂級接口

二級接口

子類

數據結構

Collection

List

Arraylist

順序結構動態數組類【數組結構】

LinkedList

鏈表結構

Vector

向量

Stack

棧(是Vector的子類)

Set

HashSet

哈希表結構(底層是HashMap)

Treeset

二叉樹結構(紅黑樹)(底層treeMap)

LinkedHashSet

Map

HashMap

鏈表散列(一個數組和鏈表的結合體)

TreeMap

二叉樹

Hashtable

哈希表


Java多線程併發之同步容器和併發容器-第一篇


說明:關於hashMap是如何解決hash衝撞問題,可以詳見凱哥寫的:《hashMap怎麼保證hash一致性的》這篇文章詳細介紹了。

我們知道,絕大部分常用的集合都是線程不安全的,但是也有線程安全的。

其中線程安全的類有:

List接口下的Vector【及Stack(因為stack是Vector的子類)】

Map接口下的:HashTable【及properties(因為properties是HashTable的子類)】

我們來看看為什麼vector和HashTable是線程的安全的?

查看vector源碼中add方法:

Java多線程併發之同步容器和併發容器-第一篇

在來看看HashTable源碼中put方法:

Java多線程併發之同步容器和併發容器-第一篇

發現了嗎?無論是vector還是hashTable都是使用了Synchronized關鍵之修飾的。使用了互斥同步鎖機制來保證線程安全性的。

在JDK 1.5版本之前,如果想要保證線程安全,使用這兩個類或者使用Collections工具類的Synxxx方法來保證線程的安全。

Java多線程併發之同步容器和併發容器-第一篇

同步容器:

這些使用類Synchronized關鍵字修飾的容器被稱為:同步容器

同步容器的缺點:

但是我們知道使用互斥鎖Synchronized在併發下是很影響效率的。那是因為將並行強制轉換成串行的。加互斥鎖後,只有等一個鎖用完之後,下一個才可以接著使用。很影響效率。

在現在大數據高併發下,有沒有更好的解決方案呢?當然有的,在JDK1.5版本之後,JDK內部為我們提供了一些併發容器。

併發容器

在一般情況不考慮併發和線程安全性問題的時候,我們使用非線程安全的集合效率更高,如果需要考慮線程安全,不考慮併發或者併發很小的情況下,可以使用同步容器。但是如果在高併發下,同步容器就不能使用了。可以使用併發容器。Java中併發容器在Java.util.concurrent包下。

Concurrent包下有很多併發相關的,本篇我們就來扒拉扒拉眾多併發相關類中和併發容器相關的十幾個類:

Java多線程併發之同步容器和併發容器-第一篇

Java多線程併發之同步容器和併發容器-第一篇

併發容器分類

大致可以分以下三類:

1:List相關的併發容器

2:Map/Set相關的併發容器

為什麼把Set劃分到Map這個分類下呢?因為在Java的設計中,Set可以理解為閹割版的Map.說白了就是隻有Key沒有Value的Map.

3:隊列相關的併發容器

從名字後綴我們就可以進行區分出來。三個分類相關類如下表:


Java多線程併發之同步容器和併發容器-第一篇


分類名稱

類名

說明

數據結構

List相關的併發容器類

CopyOnWriteArrayList

併發版的ArrayList

Map/Set相關的併發容器

ConcurrentHashMap

併發版的HashMap

CopyOnWriteArraySet

併發版的Set

ConcurrentSkipListMap

基於跳錶的併發Map

ConcurrentSkipListSet

基於跳錶的併發Set

隊列相關的併發容器

ConcurrentLinkedQueue

併發對壘

基於鏈表數據結構的

ConcurrentLinkedDeque

併發隊列

基於雙向鏈表結構

ArrayBlockingQueue

阻塞隊列

基於數組結構

LinkedBlockingDeque

阻塞對壘

基於雙向鏈表結構

PriorityBlockingQueue

線程安全的優先隊列

SynchronousQueue

讀寫成對的隊列

LinkedTransferQueue

基於鏈表的數據交換隊列

DelayQueue

延時隊列


題外話:通過上表,我們可以看出JDK中類命名規則。

1:Map/Set相關的就以Map/Set結尾;List相關的就以list結尾

2:當選隊列都已queue結尾;雙向隊列都已Deque結尾。

這種類名命名規範:見名知意。在我們自己寫代碼的時候類命名也應該這樣。

言歸正傳,我們接著來講解。先來看看第一個類。List對應的併發類.

再下一篇文章中,我們將詳細講解list對應的併發容器以及用代碼來測試ArrayList、vector以及CopyOnWriteArrayList在100個線程向list中添加1000個數據後的比較。


分享到:


相關文章: