java 集合讀寫同步_JAVA多線程學習十六 - 同步集合類的應用

1.引言

在多線程的環境中,如果想要使用容器類,就需要注意所使用的容器類是否是線程安全的。在最早開始,人們一般都在使用同步容器(Vector,HashTable),其基本的原理,就是針對容器的每一個操作,都添加synchronized來進行同步,此種方式盡管簡單,但是其性能是非常地下的,所以現在已經不怎么使用了。人們普遍會使用并發的容器,在JDK1.5之后,針對基于散列的Map,提供了新的ConcurrentHashMap,針對迭代需求的list,提供了CopyOnWriteList.

2.ConcurrentHashMap

ConcurrentHashMap使用了一種分段鎖的策略,使得map可以被多個讀寫線程并行的訪問。基本可以認為是將map的key值范圍分為多個段,這樣多個線程訪問的時候,他們需要訪問的key值在不同的段,所以可以互相不干擾,

使用不同的鎖對象來進行并發操作。

ConcurrentHashMap在使用迭代器遍歷的時候,不會報ConcurrentModificationException,提供“弱一致性”。在遍歷迭代的時候,也會反應出在迭代器創建之后的數據修改。

應用場景

針對一般的有并發需求的map,都應該使用ConcurrentHashMap. 它的性能優于Hashtable和synchronizedMap。

缺點

不是強一致性

由于是采用的分段鎖策略,所以一些數據不能保證強一致性。比如針對容器的size方法,由于線程A只是獲得了自己的分段鎖,它不能保證其他線程對容器的修改,所以此時線程A可能使用size,會得到不穩定數據。這種情況下,是對同步性能的一些折衷。如果業務需求必須滿足強一致性,才會需要對整個Map進行鎖操作。并發容器的弱一致性的概念背景,是在高并發情況下,容器的size和isEmpty之類的方法,用處不大,所以可以忍受數據不一致性。

3.CopyOnWrite容器

在JDK1.5之后,java.util.concurrent引入了兩個CopyOnWrite容器,分別是CopyOnWriteArrayList, CopyOnWriteArraySet.

顧名思義,CopyOnWrite就是在write操作之前,對集合進行Copy,針對容器的任意改操作(add,set,remove之類),都是在容器的副本上進行的。并且在修改完之后,將原容器的引用指向修改后的副本。

如果線程A得到容器list1的iterator之后,線程B對容器list1加入了新的元素,由于線程A獲得list1的iterator時候在線程B對list1進行修改前,所以線程A是看不到線程B對list1進行的任何修改。

具體到源碼,看一下add操作

48304ba5e6f9fe08f3fa1abda7d326ab.png

/**

* Appends the specified element to the end of this list.

*

* @param e element to be appended to this list

* @return {@code true} (as specified by {@link Collection#add})

*/

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);

newElements[len] = e;

setArray(newElements);

return true;

} finally {

lock.unlock();

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

可以發現,寫操作是會有個鎖lock.lock(),這保證了多線程寫操作之間的同步。之后使用Arrays.copyOf來進行數組拷貝,在修改完成后,setArray(newElements)將原來的數組引用指向新的數組。

應用場景

經常用在讀多寫少的場景,比如EventListener的添加,網站的category列表等偶爾修改,但是需要大量讀取的情景。

缺點

1.數據一致性的問題。

因為讀操作沒有用到并發控制,所以可能某個線程讀到的數據不是實時數據。

2.內存占用問題。

因為寫操作會進行數據拷貝,并且舊有的數據引用也可能被其他線程占有一段時間,這樣針對數據比較大的情況,可能會占用相當大的內存。并且由于每次寫操作都會占用額外的內存,最后進行的GC時間也可能相應的增加。

4.HashSet

HashSet內部是用的HashMap,只用了HashMap的key。

同步集合

傳統集合類在并發訪問時的問題說明:死鎖死循環

傳統方式下用Collections工具類提供的synchronizedCollection方法來獲得同步集合,分析該方法的實現源碼

Java5中提供了如下一些同步集合類:

通過看java.util.concurrent包下的介紹可以知道有哪些并發集合

ConcurrentHashMap

CopyOnWriteArrayList

CopyOnWriteArraySet

傳統方式下的Conllection在迭代結合時,不允許對集合進行修改。

根據AbstractList的checkForComodification方法的源碼,分析產生ConcurrentModificationException異常的原因。

48304ba5e6f9fe08f3fa1abda7d326ab.png

public class User implements Cloneable{

private String name;

private int age;

public User(String name, int age) {

this.name = name;

this.age = age;

}

public boolean equals(Object obj) {

if(this == obj) {

return true;

}

if(!(obj instanceof User)) {

return false;

}

User user = (User)obj;

//if(this.name==user.name && this.age==user.age)

if(this.name.equals(user.name)

&& this.age==user.age) {

return true;

}

else {

return false;

}

}

public int hashCode() {

return name.hashCode() + age;

}

public String toString() {

return "{name:'" + name + "',age:" + age + "}";

}

public Object clone() {

Object object = null;

try {

object = super.clone();

} catch (CloneNotSupportedException e) {}

return object;

}

public void setAge(int age) {

this.age = age;

}

public String getName() {

return name;

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/279119.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/279119.shtml
英文地址,請注明出處:http://en.pswp.cn/news/279119.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux下的parted工具的使用 GPT分區安裝系統

安裝系統是安裝前時候ctrlatlF2 fdisk -l parted select /dev/sdb mklabel msdos # 將GPT磁盤格式化為MBR磁盤 對大硬盤進行分區 xfs 和 ntfs Linux下的parted工具的使用也很簡單,具體操作如下: rootme:/mnt# parted /dev/sda Using /dev/sda Welcome to…

ubuntu自定義菜單_如何自定義Ubuntu的每日消息

ubuntu自定義菜單Ubuntu displays an informative message, known as the message of the day, when a user logs in at the terminal. The MOTD is fully customizable — you can add your own text and other dynamic data. 當用戶在終端上登錄時,Ubuntu將顯示信…

java避免使用orderby_java – @OrderBy在JPA中無法正常工作

OrderBy如何運作?它在以下代碼中不起作用:Employee.javapackage com.semanticbits.pojo;import java.util.List;import javax.persistence.CascadeType;import javax.persistence.Embedded;import javax.persistence.Entity;import javax.persistence.Ge…

BigDecimal四舍五入與保留位

1.引言 借用《Effactive Java》這本書中的話,float和double類型的主要設計目標是為了科學計算和工程計算。他們執行二進制浮點運算,這是為了在廣域數值范圍上提供較為精確的快速近似計算而精心設計的。然而,它們沒有提供完全精確的結果&#…

火狐web開發清楚緩存_如何使用Firefox的Web開發工具

火狐web開發清楚緩存Firefox’s Web Developer menu contains tools for inspecting pages, executing arbitrary JavaScript code, and viewing HTTP requests and other messages. Firefox 10 added an all-new Inspector tool and updated Scratchpad. Firefox的Web Develop…

Leetcode400Nth Digit第N個數字

在無限的整數序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...中找到第 n 個數字。 注意: n 是正數且在32為整形范圍內 ( n < 231)。 示例 1: 輸入: 3 輸出: 3 示例 2: 輸入: 11 輸出: 0 說明: 第11個數字在序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... 里是0&#xff0c;它是…

Java基類共同屬性設置_多選擇基類的訪問屬性-Java初學筆記

多選擇基類的訪問屬性你現在知道在定義類的訪間屬性時可用的選擇項&#xff0c;你希望使用這些類定義子類。你知道在類繼承上這些屬性所具有的效果&#xff0c;但是你如何決定到底應該使用哪一個呢?這里沒有死板和現成的規則&#xff0c;你選擇的訪問屬性取決于在將來你想用類…

IT:如何在Windows Server 2008 R2上安裝Hyper-V虛擬化

Windows Server 2008 R2 and later releases of the product ship with a virtualization platform called Hyper-V, which works quite well since it’s built into Windows. Today we’re going to show you how to install it. Windows Server 2008 R2和更高版本的產品附帶…

FineReport單行與數據庫交互的方法

1. 問題描述 我們在做一張報表填報的時候經常會遇到需要在一行進行添加動作&#xff0c;將該行數據直接與數據庫交互&#xff0c;執行存儲過程過程。我們可以通過每一行增加帆軟“插入”按鈕實現插入動作&#xff0c;并且在控件事件中增加和數據庫的交互&#xff0c;但當事件…

java cas volatile_每日一個知識點:Volatile 和 CAS 的弊端之總線風暴

每日一個知識點系列的目的是針對某一個知識點進行概括性總結&#xff0c;可在一分鐘內完成知識點的閱讀理解&#xff0c;此處不涉及詳細的原理性解讀。一、什么是總線風暴總線風暴&#xff0c;聽著真是一個帥氣的詞語&#xff0c;但如果發生在你的系統上那就不是很美麗了&#…

SqlServer之代碼塊相關

轉載必需注明出處:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/sqlserver-codeblock/ 一、go語句 Go語句是SqlServer中用來表示當前代碼塊結束提交并確認結果的語句。 Go語句不能和其他Sql命令卸載同一行上&#xff01; 定義的局部變量作用域局限在定義它的代碼…

010 使用list和tuple

list Python內置的一種數據類型是列表&#xff1a;list。list是一種有序的集合&#xff0c;可以隨時添加和刪除其中的元素。 比如&#xff0c;列出班里所有同學的名字&#xff0c;就可以用一個list表示&#xff1a; >>> classmates [Michael, Bob, Tracy] >>&g…

IT:如何使用Server 2008 R2上的遠程桌面服務設置自己的終端服務器

In today’s IT learning article, we are going to take a look at installing Terminal Services, otherwise known as Remote Desktop Services, on a Server 2008 R2 machine. 在今天的IT學習文章中&#xff0c;我們將介紹在Server 2008 R2計算機上安裝終端服務(也稱為遠程…

java 中的chartdata_獲取Helm Charts中的文件夾列表

獲得了位于templates文件夾之外的配置文件列表&#xff0c;我們將其輸入到如下的helm圖表中&#xff1a;├── configs│ ├── AllEnvironments│ │ ├── Infrastructure│ │ └── Services│ │ ├── ConfigFile1│ │ ├── ConfigFile2│ ├…

Win10 jdk的安裝以及環境變量的配置,及需要注意的坑

此篇文章獻給自己&#xff0c;希望下次長點記性 最近本人終于有時間開始學習appium&#xff0c;并且開始在電腦上配置環境&#xff0c;第一步就是在我那剛裝的Win10 系統上安裝jdk&#xff0c;過程并不順利&#xff0c;由于之前都是用的win7&#xff0c;幾乎都是一路的下一步&a…

java部分服務出現異常_Java web service 異常

1.org/apache/commons/discovery/tools/DiscoverSingletonException in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/discovery/tools/DiscoverSingleton缺少&#xff1a;commons-logging和commons-discovery2.ojava.lang.NoClassDefFoundErr…

Jenkins配置Findbugs做源代碼安全掃描

2019獨角獸企業重金招聘Python工程師標準>>> 此內容目標閱讀用戶&#xff1a;運維人員 配置步驟如下&#xff1a; Jenkins安裝Findbugs插件 Jenkins系統管理 → 管理插件 → (可選插件)找到Findbugs及其依賴插件全部安裝成功&#xff0c;Jenkins重啟&#xff0c;即可…

如何從USB運行Windows 8 Developer Preview

Running Windows 8 from a USB should not be confused with installing Windows on a USB drive–in this case, instead of installing it on the drive, we’re just running it straight from the portable drive. Here’s how to do it. 從USB運行Windows 8不應與在USB驅動…

PAT-乙級-1042 字符統計

請編寫程序&#xff0c;找出一段給定文字中出現最頻繁的那個英文字母。 輸入格式&#xff1a; 輸入在一行中給出一個長度不超過 1000 的字符串。字符串由 ASCII 碼表中任意可見字符及空格組成&#xff0c;至少包含 1 個英文字母&#xff0c;以回車結束&#xff08;回車不算在內…

acm教程 java版_[轉]ACM之java速成

這里指的java速成&#xff0c;只限于java語法&#xff0c;包括輸入輸出&#xff0c;運算處理&#xff0c;字符串和高精度的處理&#xff0c;進制之間的轉換等&#xff0c;能解決OJ上的一些高精度題目。1. 輸入&#xff1a;格式為&#xff1a;Scanner cin new Scanner(newBuffe…