1. 程式人生 > >慕課網實戰·高併發探索(九):併發容器 J.U.C

慕課網實戰·高併發探索(九):併發容器 J.U.C

特別感謝:慕課網jimin老師的《Java併發程式設計與高併發解決方案》課程,以下知識點多數來自老師的課程內容。
jimin老師課程地址:Java併發程式設計與高併發解決方案

概述

Java併發容器JUC是三個單詞的縮寫。是JDK下面的一個包名。即Java.util.concurrency。
上一節我們介紹了ArrayList、HashMap、HashSet對應的同步容器保證其執行緒安全,這節我們介紹一下其對應的併發容器。

ArrayList –> CopyOnWriteArrayList

CopyOnWriteArrayList 寫操作時複製,當有新元素新增到集合中時,從原有的陣列中拷貝一份出來,然後在新的陣列上作寫操作,將原來的陣列指向新的陣列。整個陣列的add操作都是在鎖的保護下進行的,防止併發時複製多份副本。讀操作是在原陣列中進行,不需要加鎖

  • 缺點:
    1.寫操作時複製消耗記憶體,如果元素比較多時候,容易導致young gc 和full gc。
    2.不能用於實時讀的場景.由於複製和add操作等需要時間,故讀取時可能讀到舊值。
    能做到最終一致性,但無法滿足實時性的要求,更適合讀多寫少的場景。
    如果無法知道陣列有多大,或者add,set操作有多少,慎用此類,在大量的複製副本的過程中很容易出錯。

  • 設計思想:
    1.讀寫分離
    2.最終一致性
    3.使用時另外開闢空間,防止併發衝突

  • 原始碼分析

//構造方法
public CopyOnWriteArrayList(Collection<? extends E> c) {
    Object[] elements;//使用物件陣列來承載資料
if (c.getClass() == CopyOnWriteArrayList.class) elements = ((CopyOnWriteArrayList<?>)c).getArray(); else { elements = c.toArray(); // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elements.getClass() != Object[].class) elements = Arrays.copyOf(elements, elements.length, Object[].class); } setArray(elements); } //新增資料方法
public boolean add(E e) { final ReentrantLock lock = this.lock;//使用重入鎖,保證執行緒安全 lock.lock(); try { Object[] elements = getArray();//獲取當前陣列資料 int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1);//複製當前陣列並且擴容+1 newElements[len] = e;//將要新增的資料放入新陣列 setArray(newElements);//將原來的陣列指向新的陣列 return true; } finally { lock.unlock(); } } //獲取資料方法,與普通的get沒什麼差別 private E get(Object[] a, int index) { return (E) a[index]; }
HashSet –> CopyOnWriteArraySet
  • 它是執行緒安全的,底層實現使用的是CopyOnWriteArrayList,因此它也適用於大小很小的set集合,只讀操作遠大於可變操作。因為他需要copy整個陣列,所以包括add、remove、set它的開銷相對於大一些。
  • 迭代器不支援可變的remove操作。使用迭代器遍歷的時候速度很快,而且不會與其他執行緒發生衝突。
  • 原始碼分析:
//構造方法
public CopyOnWriteArraySet() {
    al = new CopyOnWriteArrayList<E>();//底層使用CopyOnWriteArrayList
}

//新增元素方法,基本實現原理與CopyOnWriteArrayList相同
private boolean addIfAbsent(E e, Object[] snapshot) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] current = getArray();
        int len = current.length;
        if (snapshot != current) {//添加了元素去重操作
            // Optimize for lost race to another addXXX operation
            int common = Math.min(snapshot.length, len);
            for (int i = 0; i < common; i++)
                if (current[i] != snapshot[i] && eq(e, current[i]))
                    return false;
            if (indexOf(e, current, common, len) >= 0)
                    return false;
        }
        Object[] newElements = Arrays.copyOf(current, len + 1);
        newElements[len] = e;
        setArray(newElements);
        return true;
    } finally {
        lock.unlock();
    }
}
TreeSet –> ConcurrentSkipListSet

它是JDK6新增的類,同TreeSet一樣支援自然排序,並且可以在構造的時候自己定義比較器。

  • 同其他set集合,是基於map集合的(基於ConcurrentSkipListMap),在多執行緒環境下,裡面的contains、add、remove操作都是執行緒安全的。
  • 多個執行緒可以安全的併發的執行插入、移除、和訪問操作。但是對於批量操作addAll、removeAll、retainAll和containsAll並不能保證以原子方式執行,原因是addAll、removeAll、retainAll底層呼叫的還是contains、add、remove方法,只能保證每一次的執行是原子性的,代表在單一執行操縱時不會被打斷,但是不能保證每一次批量操作都不會被打斷。在使用批量操作時,還是需要手動加上同步操作的。
  • 不允許使用null元素的,它無法可靠的將引數及返回值與不存在的元素區分開來。
  • 原始碼分析:
//構造方法
public ConcurrentSkipListSet() {
    m = new ConcurrentSkipListMap<E,Object>();//使用ConcurrentSkipListMap實現
}
HashMap –> ConcurrentHashMap
  • 不允許空值,在實際的應用中除了少數的插入操作和刪除操作外,絕大多數我們使用map都是讀取操作。而且讀操作大多數都是成功的。基於這個前提,它針對讀操作做了大量的優化。因此這個類在高併發環境下有特別好的表現。
  • ConcurrentHashMap作為Concurrent一族,其有著高效地併發操作,相比Hashtable的笨重,ConcurrentHashMap則更勝一籌了。
  • 在1.8版本以前,ConcurrentHashMap採用分段鎖的概念,使鎖更加細化,但是1.8已經改變了這種思路,而是利用CAS+Synchronized來保證併發更新的安全,當然底層採用陣列+連結串列+紅黑樹的儲存結構。
TreeMap –> ConcurrentSkipListMap
  • 底層實現採用SkipList跳錶
  • 曾經有人用ConcurrentHashMap與ConcurrentSkipListMap做效能測試,在4個執行緒1.6W的資料條件下,前者的資料存取速度是後者的4倍左右。但是後者有幾個前者不能比擬的優點:
    1、Key是有序的
    2、支援更高的併發,儲存時間與執行緒數無關
安全共享物件策略
  • 執行緒限制:一個被執行緒限制的物件,由執行緒獨佔,並且只能被佔有它的執行緒修改
  • 共享只讀:一個共享只讀的U帝鄉,在沒有額外同步的情況下,可以被多個執行緒併發訪問,但是任何執行緒都不能修改它
  • 執行緒安全物件:一個執行緒安全的物件或者容器,在內部通過同步機制來保障執行緒安全,多以其他執行緒無需額外的同步就可以通過公共介面隨意訪問他
  • 被守護物件:被守護物件只能通過獲取特定的鎖來訪問。

相關推薦

實戰·併發探索併發容器 J.U.C

特別感謝:慕課網jimin老師的《Java併發程式設計與高併發解決方案》課程,以下知識點多數來自老師的課程內容。 jimin老師課程地址:Java併發程式設計與高併發解決方案 概述 Java併發容器JUC是三個單詞的縮寫。是JDK下面的一個包名。

實戰·併發探索十四執行緒池 Executor

特別感謝:慕課網jimin老師的《Java併發程式設計與高併發解決方案》課程,以下知識點多數來自老師的課程內容。 jimin老師課程地址:Java併發程式設計與高併發解決方案 new Thread的弊端 每次new Thread 新建物件,效能

實戰·併發探索執行緒封閉

特別感謝:慕課網jimin老師的《Java併發程式設計與高併發解決方案》課程,以下知識點多數來自老師的課程內容。 jimin老師課程地址:Java併發程式設計與高併發解決方案 1、什麼是執行緒封閉? 它其實就是把物件封裝到一個執行緒裡,只有一個執行緒能

實戰·併發探索執行緒安全性-可見性-有序性

可見性 什麼是可見性? 一個執行緒對主記憶體的修改可以及時的被其他執行緒觀察到 導致共享變數線上程間不可見的原因 執行緒交叉執行 重排序結合線程交叉執行 共享變數更新後的值沒有在工作記憶體與主存間及時更新 JVM處理可見性 J

實戰·併發探索十二併發容器J.U.C -- AQS元件 鎖ReentrantLock、ReentrantReadWriteLock、StempedLock

特別感謝:慕課網jimin老師的《Java併發程式設計與高併發解決方案》課程,以下知識點多數來自老師的課程內容。 jimin老師課程地址:Java併發程式設計與高併發解決方案 ReentrantLock java中有兩類鎖,一類是Synchron

】JavaScript中OOP

1.概念與繼承 面向物件程式設計(Object-oriented programming,OOP)是一種程式設計範型,同時也是一種程式開發的方法。物件指的是類的例項。它將物件作為程式的基本單元,將程式和資料封裝其中,以提高軟體的重用性、靈活性和擴充套件性。 面向物件特點:繼承、封

Python3《機器學習實戰》學習筆記支援向量機實戰篇之再撕非線性SVM

一 前言 上篇文章講解的是線性SVM的推導過程以及簡化版SMO演算法的程式碼實現。本篇文章將講解SMO演算法的優化方法以及非線性SVM。 二 SMO演算法優化 在幾百個點組成的小規模資料集上,簡化版SMO演算法的執行是沒有什麼問題

2017.4.26 --Java 併發秒殺API

Java高併發秒殺API系列(一)                  -----------------業務分析及Dao層 第一章 課程介紹 1.1 內容介紹及業務分析 (1)課程內容 1 SSM框架的整合使用 2 秒殺類系統需求理解和實現 3 常用技術解決高併發問題 (

-java併發秒殺api之併發優化-總結

1.架構優化 2.spring宣告式事務 宣告式事務:http://www.open-open.com/lib/view/open1414310646012.html 配置並使用Spring宣告式事務 在spring-service.xml中新增上配置事務管理器 <

實戰課程筆記】Vue.js仿餓了麼外賣App

寫在前面:該課程為慕課網付費課程,筆記內容程式碼居多、內容簡略,僅供自己日後翻閱。如有疑問或者不妥,歡迎提出指正,我看到了會回覆,謝謝! 第1章:課程簡介 第2章:Vuejs介紹 Ctrl+Alt+l 快捷整理程式碼 第3章:Vue-cli開啟Vue

實戰】Spark Streaming實時流處理項目實戰筆記三之銘文升級版

聚集 配置文件 ssi path fig rect 擴展 str 控制臺 銘文一級: Flume概述Flume is a distributed, reliable, and available service for efficiently collecting(收集),

實戰】Spark Streaming實時流處理項目實戰筆記五之銘文升級版

環境變量 local server 節點數 replicas conn 配置環境 park 所有 銘文一級: 單節點單broker的部署及使用 $KAFKA_HOME/config/server.propertiesbroker.id=0listenershost.name

實戰】Spark Streaming實時流處理項目實戰筆記之銘文升級版

file sin ssi 右上角 result map tap 核心 內容 銘文一級: 核心概念:StreamingContext def this(sparkContext: SparkContext, batchDuration: Duration) = { th

實戰】Spark Streaming實時流處理項目實戰筆記十之銘文升級版

state 分鐘 mooc 系統數據 使用 連接 var style stream 銘文一級: 第八章:Spark Streaming進階與案例實戰 updateStateByKey算子需求:統計到目前為止累積出現的單詞的個數(需要保持住以前的狀態) java.lang.I

實戰】Spark Streaming實時流處理項目實戰筆記十五之銘文升級版

spa for 序列 html art mat div pre paths 銘文一級:[木有筆記] 銘文二級: 第12章 Spark Streaming項目實戰 行為日誌分析: 1.訪問量的統計 2.網站黏性 3.推薦 Python實時產生數據 訪問URL->IP

實戰】Spark Streaming實時流處理項目實戰筆記十六之銘文升級版

.so zook orm 3.1 date nta highlight org 結果 銘文一級: linux crontab 網站:http://tool.lu/crontab 每一分鐘執行一次的crontab表達式: */1 * * * * crontab -e */1

實戰】Spark Streaming實時流處理項目實戰筆記十七之銘文升級版

eid 實時 root 現在 ava == oop urn 啟動 銘文一級: 功能1:今天到現在為止 實戰課程 的訪問量 yyyyMMdd courseid 使用數據庫來進行存儲我們的統計結果 Spark Streaming把統計結果寫入到數據庫裏面 可視化前端根據:yyy

實戰】Spark Streaming實時流處理項目實戰筆記二十之銘文升級版

.get frame 結果 取數據 lena echarts object 原理 四種 銘文一級: Spring Boot整合Echarts動態獲取HBase的數據1) 動態的傳遞進去當天的時間 a) 在代碼中寫死 b) 讓你查詢昨天的、前天的咋辦? 在頁面中放一個時間插

實戰】Spark Streaming實時流處理項目實戰筆記二十一之銘文升級版

win7 小時 其他 har safari 北京 web 連接 rim 銘文一級: DataV功能說明1)點擊量分省排名/運營商訪問占比 Spark SQL項目實戰課程: 通過IP就能解析到省份、城市、運營商 2)瀏覽器訪問占比/操作系統占比 Hadoop項目:userAg

超多實戰教程破解自學教程百度雲盤分享-Python/Java/前端後端/小程序/運維測試/人工智能

上線 備註 面試 漏洞 vue ret 服務號 協作平臺 java軟件 以下課程,需要的可以加我微*信:hgh813210,備註你需要的課程 Java企業級電商項目架構演進之路 Tomcat集群與Redis分布式百度雲實戰分享 前端成長必經之路 基於Storm構建實時熱力分