欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

怎么理解并掌握ConcurrentHashMap

本篇內(nèi)容主要講解“怎么理解并掌握ConcurrentHashMap”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“怎么理解并掌握ConcurrentHashMap”吧!

創(chuàng)新互聯(lián)公司制作網(wǎng)站網(wǎng)頁找三站合一網(wǎng)站制作公司,專注于網(wǎng)頁設(shè)計,成都網(wǎng)站制作、成都網(wǎng)站設(shè)計、外貿(mào)營銷網(wǎng)站建設(shè),網(wǎng)站設(shè)計,企業(yè)網(wǎng)站搭建,網(wǎng)站開發(fā),建網(wǎng)站業(yè)務(wù),680元做網(wǎng)站,已為上千多家服務(wù),創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)將一如既往的為我們的客戶提供最優(yōu)質(zhì)的網(wǎng)站建設(shè)、網(wǎng)絡(luò)營銷推廣服務(wù)!

HashMap最佳實踐

現(xiàn)在我們知道了,在實際項目中,我們是把HashMap作為容器來使用的。既然是容器,那就需要考慮這么幾個問題:

  • 容器的容量大小,能夠支持存放多少個元素,一開始給多少合適呢?(初始容量問題)

  • 指定了容器初始容量大小后,萬一元素太多,容器放不下了如何處理呢?(容器擴容、裝載因子問題)

針對上面的問題,我們來分析一下:

  • 在HashMap中,默認的初始容量大小是16, 在實際項目中,我們可以考慮預估要存入的元素個數(shù),根據(jù)元素個數(shù)設(shè)置合適的初始容量。減少HashMap動態(tài)擴容,減少重建哈希表,從而提升性能

/**
* The default initial capacity - MUST be a power of two.
* 默認初始容量,HashMap的容量最好是保持 2的n次方
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
  • HashMap裝載因子,默認是0.75。表示在HashMap中,當元素的個數(shù)超過:capacity * 0.75的時候,就會啟動動態(tài)擴容,每次擴容后容量大小都是之前的兩倍

  • 裝載因子越大,表示空閑空間越小,對應(yīng)的HashMap沖突的概率就會越大。在實際項目中,我們可以設(shè)置合適的裝載因子,提升HashMap性能

/**
* The load factor used when none specified in constructor.
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;

hash沖突詳解

現(xiàn)在你已經(jīng)知道了在項目中用好HashMap,需要考慮的一些問題:初始容量、裝載因子等。

接下來我們一起來看另外一個問題:如何解決hash沖突。關(guān)于hash沖突,單從應(yīng)用HashMap來說,我們并不需要關(guān)心,畢竟大多數(shù)時候,我們都僅僅是使用HashMap,并不會考慮從0到1寫一個HashMap。但是我還是想建議你了解一下,關(guān)于整個世界的認知,我們都應(yīng)該知其然,且知其所以然。

上一篇我們提到關(guān)于hash沖突,主要有兩種解決方案:開放尋址法,拉連法。但是當時我并沒有詳細說明,我們跳過了,現(xiàn)在我們一起來看一下,什么是開放尋址法?什么是拉鏈法?

我們知道HashMap的底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組,數(shù)組的容量是有限的(我們暫時不考慮擴容,因為擴容后容量也還是有限的,只是比起擴容前大一倍)。

我們也知道HashMap的存儲是key/value鍵值對,需要將任意類型的key,通過散列函數(shù)hash(key),轉(zhuǎn)換成數(shù)組下標,與數(shù)組聯(lián)系起來,實現(xiàn)在O(1)時間復雜度下,查找目標元素。我們直觀的看一個圖:

怎么理解并掌握ConcurrentHashMap

另外你還記得我們上一篇舉的示例嗎?hash(0+5)=5,hash(1+4)=5,hash(2+3)=5。假設(shè)當前目標數(shù)組下標是:5,那你也看到了,左右key:0+5,1+4,2+3并不相同,但是通過hash函數(shù)后,卻都指向了數(shù)組下標:5的位置。這就是hash沖突的由來。

好了,我又帶著你回顧了一遍hash沖突,現(xiàn)在我們重新回到解決hash沖突:開放尋址法、拉鏈法。

關(guān)于開放尋址法

開放尋址法,是指當發(fā)生hash沖突后,比如說某個key,通過哈希函數(shù)hash(key),指向了數(shù)組下標5的位置。此時不巧下標5的位置已經(jīng)存放了元素,即發(fā)生了hash沖突。

那么開放尋址法的做法,是從數(shù)組下標5的位置開始向后搜索,尋找到第一個空的,還未存放任何元素的下標位置,比如:8,作為當前key元素存放的位置。

我們來直觀的看一個圖:

怎么理解并掌握ConcurrentHashMap

前一個元素hash(1+4)=5,占用了數(shù)組下標5的位置;

后一個元素hash(2+3)=5,雖然指向了數(shù)組下標5位置,但是此時下標5的位置已經(jīng)被hash(1+4)元素占用,所以hash(2+3)元素只能繼續(xù)向后搜索,直到搜索到下標8的位置,發(fā)現(xiàn)下標8位置未使用,即作為元素hash(2+3)的位置。

你看,這就是開放尋址法。

關(guān)于拉鏈法

拉鏈法,是指當發(fā)生hash沖突后,比如說某個key,通過哈希函數(shù)hash(key),指向了數(shù)組下標5的位置。此時不巧下標5的位置已經(jīng)存放了元素,即發(fā)生了hash沖突。

那么拉鏈法的做法,不同于開放尋址法。它不需要從下標5的位置向后搜索,它是直接定位到下標5的位置,在此處通過鏈表,將發(fā)生hash沖突的多個元素連接起來,形成一個鏈表

我們直觀的看一個圖:

怎么理解并掌握ConcurrentHashMap

你看,這就是拉鏈法。

關(guān)于二者適用場景

現(xiàn)在你已經(jīng)知道了什么是hash沖突,以及hash沖突的兩種主要解決方案:開放尋址法、拉鏈法

我們再來探討一個問題,什么場景下適合用開放尋址法?什么場景下適合用拉鏈法呢?

我們知道開放尋址法,最大的特點就是當發(fā)生hash沖突的時候,有向后搜索的操作。那么假設(shè)在存放大量目標元素對象的場景下,發(fā)生沖突的概率會非常大,每次發(fā)生沖突,都要向后搜索操作,會比較影響性能。

因此,開放尋址法適合在容器容量需求不大(即目標元素不多),hash沖突發(fā)生概率小的場景下,我建議你可以看一下ThreadLocalMap源碼,ThreadLocalMap即使用了開放尋址法解決hash沖突。

知道了開放尋址法的適用場景后,我們通過反向思考,即不難理解拉鏈法的使用場景了。拉鏈法適合在目標元素多,容器容量需求大、hash沖突發(fā)生概率大的業(yè)務(wù)場景。不用說,你已經(jīng)知道了,我們一直的主角HashMap,ConcurrentHashMap都使用了拉鏈法解決hash沖突。

ConcurrentHashMap詳解

為了方便你理解ConcurrentHashMap,我們前面做了非常長的鋪墊,上一篇文章以及這篇文章的上半部分。

現(xiàn)在相信你已經(jīng)理解了HashMap,那我們就開始進入ConcurrentHashMap的內(nèi)容了。關(guān)于ConcurrentHashMap,大方向上你先有一個印象:ConcurrentHashMap它是HashMap的線程安全版本,它與HashMap一脈相傳,是師兄弟關(guān)系,只不過它是關(guān)門弟子,得了師傅的真?zhèn)?,能力要更加強大一?/strong>。

上面這段話的意思,大致是想要告訴你,ConcurrentHashMap的底層實現(xiàn)原理,用了什么數(shù)據(jù)結(jié)構(gòu),如何解決hash沖突等都與HashMap一樣。我們只需要關(guān)心它是如何實現(xiàn)線程安全的就可以了。

那就讓我們開始吧,你需要注意一下,ConcurrentHashMap線程安全的實現(xiàn),在jdk8版本,與jdk8以前的版本區(qū)別比較大,我們分開來說。

jdk7版本的ConcurrentHashMap

我們先來看ConcurrentHashMap在jdk8以前版本的實現(xiàn),以下我的分析,和涉及到的源碼都是參考jdk7,你先留意一下。

談到線程安全,你肯定想到了,除了加鎖沒有別的手段,并且你還進一步想到了我們在鎖小節(jié)分享的:synchronized、或者Lock對象。

這里我們初步的想法是沒有任何問題的,想要實現(xiàn)線程安全:加鎖。但是我們還需要稍微往前思考一個問題:如果只是簡單的加鎖,那不就是Hashtable了嗎?java設(shè)計者的大神們,你們是不是閑著沒事干,順便多寫了一個ConcurrentHashMap呢?

答案肯定不是的,大神之所以稱之為大神,其中有一個區(qū)別于常人的特質(zhì),就是從來不做無用功!

那要這么說,我們就需要搞清楚有了Hashtable,為什么還需要一個ConcurrentHashMap?

我們先回顧一下,Hashtable是如何實現(xiàn)線程安全的,以及它存在什么問題?你還記得嗎,前面我們在高級并發(fā)編程系列十四(并發(fā)集合基礎(chǔ))一篇,分享了Hashtable實現(xiàn)線程安全的方式,它是直接在每個操作方法上加了synchronized關(guān)鍵字。比如下圖,是我們熟悉的get方法:

怎么理解并掌握ConcurrentHashMap

我們說直接在方法上加synchronized關(guān)鍵字,實現(xiàn)線程安全有什么問題呢?最大的問題就是鎖粒度太大,導致并發(fā)性能低,不足以應(yīng)用在高并發(fā)業(yè)務(wù)場景。這也是為什么Hashtable出身以來,從未受寵的原因,你也不喜歡它對吧!千萬別說喜歡,非要喜歡的話怎么不見在你的項目中使用Hashtable呢?

說了這么多別人的不是,其目的都是為了襯托ConcurrentHashMap的主角光環(huán)。那你說說看吧,ConcurrentHashMap到底是如何實現(xiàn)線程安全,又是如何支持高并發(fā)的?我們從兩個方面來看。

既然要線程安全,那么鎖,肯定是要鎖的,基礎(chǔ)原理不變

另外要支持高并發(fā)業(yè)務(wù)場景,都加鎖了,還怎么實現(xiàn)高并發(fā)呢?這個地方你需要特別留意了,這里我將給你分享一個解決大、且復雜問題的通用思想,我們說:面對大的,復雜的業(yè)務(wù)問題,要想實現(xiàn)化繁為簡,唯一的手段即是拆分。今天我們說分布式,微服務(wù)化其核心都是拆字決!

那具體到ConcurrentHashMap中,它到底是如何拆的呢?它是這么拆的:通過分段鎖,即保障了線程安全,又提升了并發(fā)能力。

關(guān)于分段鎖,你可以這么去理解:原來是一個大鎖,限制了并發(fā)能力,因為只有一把鎖;現(xiàn)在我們把大鎖分成多把小鎖(ConcurrentHashMap默認是16個分段鎖),可以同時支持16個并發(fā)。

好了,文字分析我們差不多講明白了,接下來我通過源碼,以及畫一個圖,讓你更好的理解ConcurrentHashMap(你需要注意,我當前的jdk版本是7)。

ConcurrentHashMap圖示:

怎么理解并掌握ConcurrentHashMap

ConcurrentHashMap源碼代表:

通過上圖我們直觀看到在jdk7中,ConcurrentHashMap它是通過分段鎖實現(xiàn)支持高并發(fā),默認情況下,有16個分段鎖,其中每一個分段鎖中,即是一個HashMap。

接下來我們一起通過源碼,輔助理解上圖。

  • 底層數(shù)據(jù)結(jié)構(gòu),數(shù)組

/**
* The segments, each of which is a specialized hash table.
*/
final Segment<K,V>[] segments;
  • 分段鎖Segment定義

/**
* Segments are specialized versions of hash tables.  This
* subclasses from ReentrantLock opportunistically, just to
* simplify some locking and avoid separate construction.
* 每個Segment,原來就是一個ReentrantLock,好熟悉有沒有
*/
static final class Segment<K,V> extends ReentrantLock implements Serializable {
     ......   
}
  • 分段鎖內(nèi)部定義

/*
*每個Segment,都是一個HashMap
*/
transient volatile HashEntry<K,V>[] table;
2.3.2.jdk8版本的ConcurrentHashMap

現(xiàn)在你已經(jīng)知道了jdk7中的ConcurrentHashMap,我們說在jdk8中,它不再是分段鎖的設(shè)計思想了,它變了!

變成什么了呢?變成了cas + synchronized組合來保障線程安全,同時實現(xiàn)支持高并發(fā)。這里你還記得什么是cas嗎,如果不記得了,我推薦你看我這個系列的另外一篇文章:高級并發(fā)編程系列十二(一文搞懂cas)。

這里限于篇幅和側(cè)重關(guān)注點,我就不再詳細跟你說cas了,我只簡單帶你回顧一下cas的核心原理: cas本質(zhì)上是不到黃河心不死,即不釋放cpu,循環(huán)操作,直到操作成功為止。

它的操作原理是三個值:內(nèi)存值A(chǔ)、期望值B、更新值C。每次操作都會比較內(nèi)存值A(chǔ),是否等于期望值B、如果等于則將內(nèi)存值更新成值C,操作成功;如果內(nèi)存值A(chǔ),不等于期望值B,則操作失敗,進行下一次循環(huán)操作。

給你回顧完cas,我們主要再來關(guān)注為什么在jdk8中,ConcurrentHashMap會通過cas +synchronized組合,來替換jdk7中的分段鎖Segment呢?難道分段鎖它不香嗎?

我?guī)е阋黄鸱窒硪幌挛业膫€人理解:

  • 我們知道cas是一種無鎖化機制,大家都可以并行來搶占cpu(因為不加鎖嘛),自然是你可以搶,我也可以搶

  • 那要這么說,cas就非常適合并發(fā)沖突小,加鎖臨界點(范圍)小的應(yīng)用場景。

  • 請說人話:什么是并發(fā)沖突?。亢唵握f就是讀多寫少的業(yè)務(wù)場景,即讀不需要加鎖,寫才需要加鎖

  • 嗯,你這么說我就明白了,我們在項目中使用HashMap,正好都是讀多寫少,一次寫入,多次讀取的業(yè)務(wù)場景。比如本地緩存實現(xiàn)方案

  • 因此cas+synchronized組合實現(xiàn)ConcurrentHashMap的方案,在實際應(yīng)用中,會比分段鎖的實現(xiàn)方案,帶來更高的并發(fā)支持,性能會更好!

你看,這么說,你是不是也能理解jdk8中的ConcurrentHashMap了。最后我們還是看一個圖吧。

這個圖你見過了,就是我們上一篇中HashMap的圖。在jdk8中ConcurrentHashMap的底層數(shù)據(jù)結(jié)構(gòu)上,與HashMap完全一樣,它只是增加了cas+synchronized操作。話不多說,我們看圖:

怎么理解并掌握ConcurrentHashMap

到此,相信大家對“怎么理解并掌握ConcurrentHashMap”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學習!

網(wǎng)站題目:怎么理解并掌握ConcurrentHashMap
網(wǎng)頁地址:http://aaarwkj.com/article30/iijgso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、微信小程序、網(wǎng)站制作、網(wǎng)站建設(shè)、建站公司網(wǎng)站內(nèi)鏈

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

日韩不伦高清一区二区三区| 国产精品成人亚洲一区二区| 亚洲色图综合在线观看| 国产精品色网在线播放| 欧美劲爆三级免费观看| 六十路人妻一区二区三区| 亚洲男人的天堂社区av| 91啪在线观看91色| 蜜臀av首页在线观看| 日日夜夜天天操天天干| 国产区精品福利在线熟女| 91日本视频在线播放| 亚洲综合日韩欧美一区二区三区| 国产尤物直播在线观看| 欧美精品黑人三级精品| 国产精品十八禁在线看| 国产av蜜臀一区二区三区| 国产色视频一区在线观看| 国产精品伊人久久综合网| 欧美另类精品一区二区三区| 天天免费日日夜夜夜夜| 欧美成人黄片免费播放| av永久免费观看网站| av一区二区三区高潮| 亚洲av污精品一区二区三区| 中文字幕乱码高清欧美日韩| 国产成人国产精品国产三级| 亚洲成人高清在线播放| 日韩国产精品视频二区| 欧美日本国产专区一区| 国产午夜福利视频合集| 我要看国产一级内射片| 综合av在线一区天堂| 国产一区av麻豆免费观看| 九七青青草视频在线观看| 日本 一区二区在线| 欧美精品色精品免费观看| 久国产亚洲精品久久久极品| 伊人色综合久久天天五月婷| 不卡一区二区三区av电影| 蜜臀av在线国产一区|