多執行緒與高併發7 容器

2021-10-04 10:09:10 字數 2882 閱讀 3725

queue佇列:主要就是為高併發而存在,有進有出。

deque雙關佇列:頭和尾都可以訪問

blockingqueue阻塞佇列:

priorityqueue優先佇列:按照順序先入先出

delayqueue延遲佇列:佇列中的物件只有到期之後才能被取走

一代同步容器,所有的方法均上鎖,基本不用

hashtable,hashmap,synchroizedhashmap,concurrenthashmap

hashtable:jdk1.0時代,所有的方法都上了鎖,效能較差

hashmap:效率高卻無鎖

synchronizedhashmap:為解決hashmap無鎖的問題,collections工具類提供的轉換方法。hashtable直接給方法上鎖,這個是通過乙個物件進行上鎖效率稍高。

collections.

synchronizedmap

(new

hashmap

<

>

);

concurrenthashmap:併發table

採用分段式鎖設計,concurrenthashmap的主幹是個segment陣列。segment繼承了reentrantlock,所以它就是一種可重入鎖(reentrantlock)。

segment裡維護了乙個hashentry陣列,併發環境下,對於不同segment的資料進行操作是不用考慮鎖競爭的。(就按預設的concurrentleve為16來講,理論上就允許16個執行緒併發執行,有木有很酷)

所以,對於同乙個segment的操作才需考慮執行緒同步,不同的segment則無需考慮。

(put1.定位segment並確保定位的segment已初始化 2.呼叫segment的put方法。)

(get方法無需加鎖,由於其中涉及到的共享變數都使用volatile修飾,volatile可以保證記憶體可見性,所以不會讀取到過期資料。)

在寫效率上來說,主要還是要看併發數和執行緒數,如果小併發情況下,sync式的map並不一定比concurrenthashmap低。(sync鎖公升級)。高併發情況下使用concurrenthashmap.

在讀效率上,concurrenthashmap比hashtable和synctable效率高數十倍

arraylist執行緒不安全,多個執行緒訪問產生超賣現象

vector執行緒安全,但所有的方法都上了鎖

concurrentlinkedqueue在多執行緒條件下,如果沒有不能重複執行緒,盡量使用queue。queue提供了很多對多執行緒友好的api [ offer() peek() poll() ]

對於blockingqueue [ put() take() ]

queue q =

newconcurrentlinkedqueue

<

>()

;q.add();

q.poll()

;

非執行緒同步:hashmap,treemap(紅黑樹排序,查詢速度快)

執行緒同步:concurrenthashmap,concurrentskiplistmap(跳表,cas實現於tree太複雜,通過跳表實現。也是redis zset底層)

跳表結構,底層仍是鍊錶(排序),選舉出父節點,父節點們仍是鍊錶結構(並行鍊錶),如果元素較多再次選舉。查詢時,通過父節點之間的範圍,最終獲得到該節點。

效率要比鍊錶快很多(o(n),o(logn))

應用:多執行緒併發,寫操作少讀操作多的情況。寫的時候sync,通過arrays.copyof交換新增元素後的新陣列。讀時沒有加鎖(除新增元素,其他元素一模一樣沒必要加鎖)

寫時複製,在新增元素時,複製乙個array將元素放到最後的位置,然後指向新的位址。

linkedblockingqueue無界的 (不超過integer.max_value)

arrayblockingqueue有界的

delayqueue在時間上排序

synchronousqueue在兩個執行緒間傳遞任務

transferqueue以上q集合

queue常用方法:

offer()新增元素,返回是否新增元素成功的返回值

peek()取出元素,並不會去掉元素

poll()取出元素,並且去掉元素

blockingqueue常用方法(天生實現生產消費者):

put()放入元素,如果滿了就會等待

take()取出元素,如無元素可取,將會阻塞

arrayblockingqueue

構造方法可以確定大小,到達閾值後:

put方法執行,將不會新增元素,並阻塞;

add方法執行,將丟擲異常,full queue;

offer方法執行,不會新增元素,返回值false,構造方法可傳入時間來嘗試新增

delayqueue

可根據時間進行執行任務,定時任務排程

priorityqueue

不按照插入順序取出,通過優先順序排序,最小的先出

synchronusqueue

容量為零,作用不是用來裝載元素的,而是給其他執行緒下達任務的。

使用add()會異常,因為容量為0,不能夠新增元素。只能使用put()進行阻塞操作,等待take()取走元素

transferqueue

linkedtransferqueue

transfer(「test」); 新增元素後,阻塞,等待取走元素。

場景:必須確定消費者取走元素。

多執行緒與高併發

blocked 鎖池 timed waiting 定時等待 waiting 等待 terminated 禁止指令重排序 記憶體屏障 在單例雙重檢查中,不加會出現使用半初始化的值,也就是還未附初始值,指令重排導致的 類載入與指令重排的知識 public class spinlock while fla...

多執行緒與併發6 併發容器

hashtable所以方法預設加sychronized,hashmap預設沒有加鎖,而synchronizedhashmap預設是collections.synchronizedmap mapmap 返回乙個同步map。currenthashmap是多線 正用的,本來是拉鍊表,jdk1.8後變成紅黑...

多執行緒與高併發 一

建立乙個執行緒的兩種方式 繼承threadclass mythread extends thread newmythread start 實現runnable介面class mythread implements runnable newthread new myrun start 面試時候有時候會...