1. 程式人生 > >Java常用併發容器總結(二)

Java常用併發容器總結(二)

ConcurrentHashMap

1.介紹

ConcurrentHashMap是一個高效併發的HashMap,它採用了減小鎖粒度的手段,內部進一步細分成了若干個小的HashMap,稱為Segment段。預設情況下,一個ConcurrentHashMap被分為16個段。多ConcurrentHashMap操作時,並不是將整個ConcurrentHashMap加鎖,而是首先根據hashCode定位到要操作的Segment,然後對該段進行加鎖。在多執行緒環境下,如果多個執行緒操作同一個ConcurrentHashMap的不同Segment,可以做到真正的並行,大大提高了效率。

2.程式碼分析

下面以ConcurrentHashMap的put()方法為例,分析ConcurrentHashMap的操作策略:

public V put(K key, V value) {
        Segment<K,V> s;
        if (value == null)
            throw new NullPointerException();

        //計算key的hashCode
        int hash = hash(key);

        //根據hashCode,找到要進行操作的段
        int j = (hash >>> segmentShift) & segmentMask;
        if
((s = (Segment<K,V>)UNSAFE.getObject (segments, (j << SSHIFT) + SBASE)) == null) s = ensureSegment(j); //對該段進行put return s.put(key, hash, value, false); }

可以看出,對ConcurrentHashMap的put操作,可以將粒度減小為對某一個Segment的操作,大大減小了鎖的競爭,提高併發效率。
但是,減小鎖的粒度引入了一個新的問題,當系統需要獲得全域性鎖時,消耗的資源較多。以size()方法為例:

public int size() {       
        final Segment<K,V>[] segments = this.segments;
        int size;
        boolean overflow; 
        long sum;        
        long last = 0L;  
        int retries = -1; 
        try {
            for (;;) {
                if (retries++ == RETRIES_BEFORE_LOCK) {
                    for (int j = 0; j < segments.length; ++j)

                        //在這裡,需要多每一個Segment分別加鎖
                        ensureSegment(j).lock(); 
                }
                sum = 0L;
                size = 0;
                overflow = false;
                for (int j = 0; j < segments.length; ++j) {
                    Segment<K,V> seg = segmentAt(segments, j);
                    if (seg != null) {

                        //計算size總數
                        sum += seg.modCount;
                        int c = seg.count;
                        if (c < 0 || (size += c) < 0)
                            overflow = true;
                    }
                }
                if (sum == last)
                    break;
                last = sum;
            }
        } finally {
            if (retries > RETRIES_BEFORE_LOCK) {
                for (int j = 0; j < segments.length; ++j)

                    //這裡再分別釋放每一段的鎖
                    segmentAt(segments, j).unlock();
            }
        }
        return overflow ? Integer.MAX_VALUE : size;
    }

可以看出,在高併發的場景下,ConcurrentHashMap的size()方法的效率要明顯低於HashMap。

3.適用場景

簡單地說,如果想在高併發的場景下使用HashMap,那麼ConcurrentHashMap將是一個很好的選擇。

相關推薦

Java常用併發容器總結()

ConcurrentHashMap 1.介紹 ConcurrentHashMap是一個高效併發的HashMap,它採用了減小鎖粒度的手段,內部進一步細分成了若干個小的HashMap,稱為Segment段。預設情況下,一個ConcurrentHashMap

Java常用併發容器總結(四)

ConcurrentSkipListMap 1.介紹 跳錶是一種可以用來快速查詢的資料結構,類似於平衡樹,他們都可以對元素進行快速的查詢。但一個重要的區別是:對平衡樹的插入往往可能導致平衡樹進行一次全域性的調整;而對跳錶的插入和刪除之需要的區域性資料操作即可

學習筆記 --- Java 併發程式設計總結 ThreadLocal

ThreadLocal是什麼 ThreadLocal是一個本地執行緒副本變數工具類。主要用於將私有執行緒和該執行緒存放的副本物件做一個對映,各個執行緒之間的變數互不干擾,在高併發場景下,可以實現無狀態的呼叫,特別適用於各個執行緒依賴不通的變數值完成操作的場景。 下圖為Threa

Android-Java:常用基本容器學習總結

Android-Java:常用基本容器學習總結 1.常用容器的總體框架 2.常用容器類的重點 1. ArrayList https://www.cnblogs.com/skywang12345/p/3308556.html 1.1 儲存結構: value值存在

Java常用代碼總結

[] blog http ati target catch () log 字符串格式化 原創作品,可以轉載,但是請標註出處地址:http://www.cnblogs.com/V1haoge/p/7004474.html 1、日期與字符串之間的轉換 1 publ

Java 常用排序演算法總結

氣泡排序:  /*冒泡演算法*/ public class BubbleSort { public static void bubble_sort(int[] arr){ int temp; for(int i = 0; i < arr

java常用工具類()—— JSON處理工具類

tor ast val simple sta 轉換 local pass password package com.springboot.commons.utils; import com.springboot.commons.scan.JacksonObjectMapp

Java IO流學習總結:File

Java File類的功能非常強大,利用java基本上可以對檔案進行所有操作。首先來看File類的建構函式的原始碼 /** * Internal constructor for already-normalized pathname strings. */ private F

Java常用集合知識點總結

特點 key map ima shm src 有一個 安全 index Java集合學習總結 首先,區分最頂層接口的區別:Collection和Map的區別:前者是單個元素;後者存儲的是一對元素。Collection有List和Set兩個子接口,兩個子接口下分別有Vect

JAVA常用面試題總結

JAVA常用面試題總結   一、SpringMVC執行原理 SpringMVC執行原理 1. 客戶端請求提交到DispatcherServlet 2. 由DispatcherServlet控制器查詢一個或多個HandlerMapping,找到處理請求的Cont

通俗易懂,JDK 併發容器總結

該文已加入開源專案:JavaGuide(一份涵蓋大部分Java程式設計師所需要掌握的核心知識的文件類專案,Star 數接近 16k)。地址:github.com/Snailclimb/…. 一 JDK 提供的併發容器總結 實戰Java高併發程式設計》為我們總結了下面幾種大家可能會在高併發程式設計

java 常用集合類總結

在平常的程式碼開發中,集合類是經常會使用到的,比如用於列表快取的ArrayList,用於做對映關係的Map等等 最近重點看了下java集合類的層次繼承關係和內部儲存結構,做個總結以便後面可以隨時翻翻。        java中的集合,不管是List,Set,還是Map,都

java常用位元組流總結

前言:流的淺顯總結(總結了常用的流的操作和一些關鍵點):之前我對流的概念理解很片面,認為所謂輸入輸出流,都是面對程式和檔案的概念但是,我發現其實比較片面,而且疏漏點很多,其實也有程式和非本程式範圍內的記憶體之間,最終不是都結束於檔案和外存,在對已經載入到了記憶體中的資料的讀和

java常用API知識點總結

------- android培訓、java培訓、期待與您交流!---------- StringBuffer: 概念:字串緩衝區,緩衝區用於儲存資料,所以也稱之為容器.字串的組成原理就是通過該類實現的. StringBuffer(掌握) (1)用字串做拼接,比較耗時並且也耗記憶體,而這種拼接操作

Java Executor併發框架()RejectedExecutionHandler介紹

一、介紹 當Executor已經關閉(即執行了executorService.shutdown()方法後),並且Executor將有限邊界用於最大執行緒數量和工作佇列容量,且已經飽和時,在方法execute()中提交的新任務將被拒絕。 在以上述情況下,execute

Java常用資料結構總結

資料元素相互之間的關係稱為結構。有四類基本結構:集合、線性結構、樹形結構、圖狀結構;集合結構:除了同屬於一種類型外,別無其它關係線性結構:元素之間存在一對一關係常見型別有: 陣列,連結串列,佇列,棧,它

java常用設計模式總結

掌握常用的幾種(最起碼單例模式、工廠模式),瞭解其他的設計模式即可,做到手裡有糧,心裡不慌。首先,掌握每種模式的定義及使用場景。其次,掌握一個形象的例子,簡單的過一遍程式碼。 學習設計模式的真正目的:程式設計時,有意識地面向介面程式設計,多用封裝、繼承、組合、

java併發程式設計總結三:JDK併發包之ReentrantLock重入鎖

為了更好的支援併發程式,jdk內部提供了大量實用的API和框架,重入鎖就是一種對同步的擴充套件 ReentrantLock起源 在1.5的時候,synchronized關鍵的效能不是很好,這也是concurrent併發包出現的一種潛在原因,而新出

java併發經驗總結

   前不久,我做了一下java高併發場景的處理,在這裡總結一下:場景主要包括兩個方面:一個是減庫存,一個是記錄訂單。簡單分析一下業務:每個客戶端下單,伺服器在資料庫上面都相應的執行兩個操作,第一步把

JAVA中的容器總結

1 容器概念 1.1 容器是什麼 在Java當中,如果有一個類專門用來存放其它類的物件,這個類就叫做容器 是將若干性質相同或相近的類物件組合在一起而形成的一個整體 1.2 容器