欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java 中ConcurrentHashMap的實(shí)現(xiàn)

 更新時(shí)間:2016年09月09日 08:47:04   作者:Giraffe  
本文主要介紹Java 中ConcurrentHashMap的實(shí)現(xiàn),這里整理了詳細(xì)的資料,及簡單實(shí)例代碼,有興趣的小伙伴可以參考下

ConcurrentHashMap(簡稱CHM)是在Java 1.5作為Hashtable的替代選擇新引入的,是concurrent包的重要成員。在Java 1.5之前,如果想要實(shí)現(xiàn)一個(gè)可以在多線程和并發(fā)的程序中安全使用的Map,只能在HashTable和synchronized Map中選擇,因?yàn)镠ashMap并不是線程安全的。但再引入了CHM之后,我們有了更好的選擇。CHM不但是線程安全的,而且比HashTable和synchronizedMap的性能要好。相對于HashTable和synchronizedMap鎖住了整個(gè)Map,CHM只鎖住部分Map。CHM允許并發(fā)的讀操作,同時(shí)通過同步鎖在寫操作時(shí)保持?jǐn)?shù)據(jù)完整性。我們已經(jīng)在Top 5 Java Concurrent Collections from JDK 5 and 6中學(xué)習(xí)了CHM的基礎(chǔ)知識(shí),在這篇博客中我將介紹以下幾點(diǎn):

  1. CHM在Java中如何實(shí)現(xiàn)的
  2. 什么情況下應(yīng)該使用CHM
  3. 在Java中使用CHM的例子
  4. CHM的一些重要特性

Java中ConcurrentHashMap的實(shí)現(xiàn)

CHM引入了分割,并提供了HashTable支持的所有的功能。在CHM中,支持多線程對Map做讀操作,并且不需要任何的blocking。這得益于CHM將Map分割成了不同的部分,在執(zhí)行更新操作時(shí)只鎖住一部分。根據(jù)默認(rèn)的并發(fā)級別(concurrency level),Map被分割成16個(gè)部分,并且由不同的鎖控制。這意味著,同時(shí)最多可以有16個(gè)寫線程操作Map。試想一下,由只能一個(gè)線程進(jìn)入變成同時(shí)可由16個(gè)寫線程同時(shí)進(jìn)入(讀線程幾乎不受限制),性能的提升是顯而易見的。但由于一些更新操作,如put(),remove(),putAll(),clear()只鎖住操作的部分,所以在檢索操作不能保證返回的是最新的結(jié)果。

另一個(gè)重要點(diǎn)是在迭代遍歷CHM時(shí),keySet返回的iterator是弱一致和fail-safe的,可能不會(huì)返回某些最近的改變,并且在遍歷過程中,如果已經(jīng)遍歷的數(shù)組上的內(nèi)容變化了,不會(huì)拋出ConcurrentModificationExceptoin的異常。

CHM默認(rèn)的并發(fā)級別是16,但可以在創(chuàng)建CHM時(shí)通過構(gòu)造函數(shù)改變。毫無疑問,并發(fā)級別代表著并發(fā)執(zhí)行更新操作的數(shù)目,所以如果只有很少的線程會(huì)更新Map,那么建議設(shè)置一個(gè)低的并發(fā)級別。另外,CHM還使用了ReentrantLock來對segments加鎖。

Java中ConcurrentHashMap putifAbsent方法的例子

很多時(shí)候我們希望在元素不存在時(shí)插入元素,我們一般會(huì)像下面那樣寫代碼

synchronized(map){
 if (map.get(key) == null){
  return map.put(key, value);
 } else{
  return map.get(key);
 }
}

上面這段代碼在HashMap和HashTable中是好用的,但在CHM中是有出錯(cuò)的風(fēng)險(xiǎn)的。這是因?yàn)镃HM在put操作時(shí)并沒有對整個(gè)Map加鎖,所以一個(gè)線程正在put(k,v)的時(shí)候,另一個(gè)線程調(diào)用get(k)會(huì)得到null,這就會(huì)造成一個(gè)線程put的值會(huì)被另一個(gè)線程put的值所覆蓋。當(dāng)然,你可以將代碼封裝到synchronized代碼塊中,這樣雖然線程安全了,但會(huì)使你的代碼變成了單線程。CHM提供的putIfAbsent(key,value)方法原子性的實(shí)現(xiàn)了同樣的功能,同時(shí)避免了上面的線程競爭的風(fēng)險(xiǎn)。

什么時(shí)候使用ConcurrentHashMap

CHM適用于讀者數(shù)量超過寫者時(shí),當(dāng)寫者數(shù)量大于等于讀者時(shí),CHM的性能是低于Hashtable和synchronized Map的。這是因?yàn)楫?dāng)鎖住了整個(gè)Map時(shí),讀操作要等待對同一部分執(zhí)行寫操作的線程結(jié)束。CHM適用于做cache,在程序啟動(dòng)時(shí)初始化,之后可以被多個(gè)請求線程訪問。正如Javadoc說明的那樣,CHM是HashTable一個(gè)很好的替代,但要記住,CHM的比HashTable的同步性稍弱。

總結(jié)

現(xiàn)在我們知道了什么是ConcurrentHashMap和什么時(shí)候該用ConcurrentHashMap,下面我們來復(fù)習(xí)一下CHM的一些關(guān)鍵點(diǎn)。

  1. CHM允許并發(fā)的讀和線程安全的更新操作
  2. 在執(zhí)行寫操作時(shí),CHM只鎖住部分的Map
  3. 并發(fā)的更新是通過內(nèi)部根據(jù)并發(fā)級別將Map分割成小部分實(shí)現(xiàn)的
  4. 高的并發(fā)級別會(huì)造成時(shí)間和空間的浪費(fèi),低的并發(fā)級別在寫線程多時(shí)會(huì)引起線程間的競爭
  5. CHM的所有操作都是線程安全
  6. CHM返回的迭代器是弱一致性,fail-safe并且不會(huì)拋出ConcurrentModificationException異常
  7. CHM不允許null的鍵值
  8. 可以使用CHM代替HashTable,但要記住CHM不會(huì)鎖住整個(gè)Map

以上就是Java中CHM的實(shí)現(xiàn)和使用場景,希望能幫助到大家!謝謝大家對本站的支持!

相關(guān)文章

  • java如何讀取某個(gè)文件夾中的全部文件(包括子文件夾)

    java如何讀取某個(gè)文件夾中的全部文件(包括子文件夾)

    這篇文章主要介紹了java如何讀取某個(gè)文件夾中的全部文件(包括子文件夾),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Java中的@SneakyThrows注解詳解

    Java中的@SneakyThrows注解詳解

    這篇文章主要介紹了Java中的@SneakyThrows注解詳解,@SneakyThrows將當(dāng)前方法拋出的異常,包裝成RuntimeException,騙過編譯器,使得調(diào)用點(diǎn)可以不用顯示處理異常信息,需要的朋友可以參考下
    2023-10-10
  • 基于Socket類以及ServerSocket類的實(shí)例講解

    基于Socket類以及ServerSocket類的實(shí)例講解

    下面小編就為大家?guī)硪黄赟ocket類以及ServerSocket類的實(shí)例講解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • Java詳細(xì)解析下拉菜單和彈出菜單的使用

    Java詳細(xì)解析下拉菜單和彈出菜單的使用

    這篇文章主要介紹了怎么用Java來創(chuàng)建和使用下拉菜單和彈出菜單,下拉菜單和彈出菜單是我們經(jīng)常要用的工具,但是你有想過自己怎么去實(shí)現(xiàn)它嗎,感興趣的朋友跟隨文章往下看看吧
    2022-04-04
  • Java實(shí)現(xiàn)單向鏈表的基本功能詳解

    Java實(shí)現(xiàn)單向鏈表的基本功能詳解

    這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)單向鏈表基本功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03
  • Java中SpringBoot的@Transactional原理

    Java中SpringBoot的@Transactional原理

    這篇文章主要介紹了Java中SpringBoot的@Transactional原理,面向元數(shù)據(jù)遍歷已經(jīng)成為越來越多開發(fā)者的偏好,因此原理從Springboot的EnableTransactionManagement注解說起,需要的朋友可以參考下
    2023-07-07
  • java使用Validation進(jìn)行數(shù)據(jù)校驗(yàn)的方式總結(jié)

    java使用Validation進(jìn)行數(shù)據(jù)校驗(yàn)的方式總結(jié)

    在Java中提供了一系列的校驗(yàn)方式,下面這篇文章主要給大家介紹了關(guān)于java使用Validation進(jìn)行數(shù)據(jù)校驗(yàn)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • Netty中ChannelPoolHandler調(diào)用處理程序詳解

    Netty中ChannelPoolHandler調(diào)用處理程序詳解

    這篇文章主要介紹了Netty中ChannelPoolHandler調(diào)用處理程序詳解,Netty 是基于 Java NIO 的異步事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用框架,使用 Netty 可以快速開發(fā)網(wǎng)絡(luò)應(yīng)用,Netty 提供了高層次的抽象來簡化 TCP 和 UDP 服務(wù)器的編程,但是你仍然可以使用底層的 API,需要的朋友可以參考下
    2023-11-11
  • Java+MySQL實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)源碼

    Java+MySQL實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)源碼

    這篇文章主要為大家詳細(xì)介紹了Java+MySQL實(shí)現(xiàn)學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • 史上最難的一道Java面試題

    史上最難的一道Java面試題

    本文給大家分享一道史上最難的一道Java面試題,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧
    2018-03-03

最新評論