Java-JUC(四):同步容器介绍
同步容器简介
针对容器我们知道有HashMap,HashTable,其中HashMap是一个非线程安全的,HashMap在并发执行put操作时会引起死循环,导致CPU利用率接近100%。因为多线程会导致HashMap的Node链表形成环形数据结构,一旦形成环形数据结构,Node的next节点永远不为空,就会在获取Node时产生死循环,而且死循环发生在发生在扩容时。
HashTable是线程安全的,但是在复合操作上会线程不安全的现象。
备注:
1)什么是复合操作?比如添加元素,需先判断是否元素存在,元素不存在时才添加。
2)hashtable是在插入和删除上都是索表的方式,因此效率特别低。
在jdk1.5之后提供java.util.concurrent包下的一些同步容器:java.util.concurrent.ConcurrentHashMap<K, V>。
ConcurrentHashMap性能讲解:
ConcurrentHashMap的性能要比HashTable性能高,而且高很多。
1)ConcurrentHashMap在jdk1.7之前采用了“锁分段”机制,默认把一个ConcurrentHashMap分为16个segment,每个segment下默认也是长度为16的哈希表,在每个哈希元素下是链表。这样就可默认每段有一个锁,一次可以最大并发操作16。

2)在jdk1.8之后ConcurrentHashMap采用CAS算法,可以把CAS算法错略的认为是无锁算法。
3)java.util.concurrent包还提供了设计用于多线程上下文中的Collection实现:ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentSkipListSet、CopyOnWriteArrayList和CopyOnWriteArraySet。
4)当希望许多线程访问一个给定的Collection时
a)ConcurrentHashMap由于同步的HashMap;
b)ConcurrentSkipListMap通常优于同步的TreeMap;
5)当期望的读数和遍历远远大于列表的更新数时,CopyOnWriteArrayList优于同步的ArrayList。
CopyOnWriteArrayList的用法示例:
测试ArrayList并发读写:
package com.dx.juc.test; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; public class CopyOnWriteTest {
public static void main(String[] args) {
new Thread(new MyCopyOnWrite()).start();
}
} class MyCopyOnWrite implements Runnable {
private static List<String> items = Collections.synchronizedList(new ArrayList<String>()); static {
items.add("A");
items.add("B");
items.add("C");
} public void run() {
for (String item : items) {
System.out.println(item);
items.add("D");
}
} }
在执行时,抛出异常:
A
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at com.dx.juc.test.MyCopyOnWrite.run(CopyOnWriteTest.java:23)
at java.lang.Thread.run(Thread.java:745)
如果使用CopyOnWriteArrayList时,并不会抛出异常,原理是每次在写入时,会在底层拷贝一份新的数据,因此如果是写入时性能不高。
package com.dx.juc.test; import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList; public class CopyOnWriteTest {
public static void main(String[] args) {
MyCopyOnWrite myCopyOnWrite = new MyCopyOnWrite(); for (int i = 0; i < 5; i++) {
new Thread(myCopyOnWrite).start();
}
}
} class MyCopyOnWrite implements Runnable {
private static CopyOnWriteArrayList<String> items = new CopyOnWriteArrayList<String>(); static {
items.add("A");
items.add("B");
items.add("C");
} public void run() {
System.out.println(Thread.currentThread().getName() + ":start");
Iterator<String> iterator = items.iterator();
while (iterator.hasNext()) {
System.out.println(Thread.currentThread().getName() + ":" + iterator.next());
items.add("D");
}
System.out.println(Thread.currentThread().getName() + ":end");
} }
Java-JUC(四):同步容器介绍的更多相关文章
- java多线程总结-同步容器与并发容器的对比与介绍
1 容器集简单介绍 java.util包下面的容器集主要有两种,一种是Collection接口下面的List和Set,一种是Map, 大致结构如下: Collection List LinkedLis ...
- java并发:同步容器&并发容器
第一节 同步容器.并发容器 1.简述同步容器与并发容器 在Java并发编程中,经常听到同步容器.并发容器之说,那什么是同步容器与并发容器呢?同步容器可以简单地理解为通过synchronized来实现同 ...
- Java线程安全同步容器
线程安全同步容器(使用 synchronized关键字) 1.ArrayList->Vector,Stack 2.HashMap->HashTable(key.value不能为null) ...
- java 并发 (四) ---- 并发容器
Hashmap 和 Concurrenthashmap Hashmap 不适合并发,应该使用ConcurrentHashMap . 这是很多人都知道的,但是为什么呢? 可以先看一下这两篇文章. JDK ...
- Java并发编程--同步容器
BlockingQueue 阻塞队列 对于阻塞队列,如果BlockingQueue是空的,从BlockingQueue取东西的操作将会被阻断进入等待状态,直到BlockingQueue进了东西才会被唤 ...
- 【转】Java并发编程:同步容器
为了方便编写出线程安全的程序,Java里面提供了一些线程安全类和并发工具,比如:同步容器.并发容器.阻塞队列.Synchronizer(比如CountDownLatch).今天我们就来讨论下同步容器. ...
- 【Java并发编程二】同步容器和并发容器
一.同步容器 在Java中,同步容器包括两个部分,一个是vector和HashTable,查看vector.HashTable的实现代码,可以看到这些容器实现线程安全的方式就是将它们的状态封装起来,并 ...
- Java并发—同步容器和并发容器
简述同步容器与并发容器 在Java并发编程中,经常听到同步容器.并发容器之说,那什么是同步容器与并发容器呢?同步容器可以简单地理解为通过synchronized来实现同步的容器,比如Vector.Ha ...
- Java并发编程:同步容器
Java并发编程:同步容器 为了方便编写出线程安全的程序,Java里面提供了一些线程安全类和并发工具,比如:同步容器.并发容器.阻塞队列.Synchronizer(比如CountDownLatch). ...
随机推荐
- SQL Server、Oracle和MySQL中查出值为NULL的替换
参考文献: http://database.51cto.com/art/200803/67397.htm 正文 在SQL Server Oracle MySQL当数据库中查出某值为NULL怎么办? 1 ...
- drp错误集锦---“Cannot return from outside a function or method”
好久都不动的项目,今天打开项目突然是红色感叹号.详细错误表现为: 也就是说,如今MyEclipse已经不识别在JSP页面中使用的return方法了(并且不止一处这种警告),那怎么办?????顿时闹钟一 ...
- delphi dxRibbon中 F10快捷键不好用的原因
最近在项目中使用ribbon ,用F10做快捷键,但是不好用, 不好用的原因是dxBarManager1 中的有个选项UseF10ForMenu, 把这项关闭就可以了
- 从.snk文件导出密钥
先声明该文的实用性不强, 要产生一对密钥可以有更简单的方法.该文简单解释了.snk文件的格式,并给出了从中提取密钥的C#代码. .snk文件(Strong Name Key)也可以叫签名文件,它一般用 ...
- 快速打开 Mac OS X 隐藏的用户资源库文件夹
在较高版本的 Mac OS X 中,用户的资源库文件夹(/Users/username/Library)默认被系统隐藏了,从 Finder 窗口中不能直接打开. 下面介绍一个非常简单的方法来快速打开用 ...
- lodash用法系列(2),处理对象
Lodash用来操作对象和集合,比Underscore拥有更多的功能和更好的性能. 官网:https://lodash.com/引用:<script src="//cdnjs.clou ...
- 沉浸式Web初体验
沉浸就是让人专注在当前的情境下感到愉悦和满足,而忘记真实世界的情境.心流理论能有力解释人们废寝忘食地投入一件事情的状态. 心流理论的核心就是说当人的技能与挑战最佳匹配时能达到心流状态.比如玩一个游戏, ...
- 在ASP.NET MVC中实现一种不同于平常的三级联动、级联方式, 可用于城市、车型选择等多层级联场景
三级或多级联动的场景经常会碰到,比如省.市.区,比如品牌.车系.车型,比如类别的多级联动......我们首先想到的是用三个select来展示,这是最通常的做法.但在另外一些场景中,比如确定搜索条件的时 ...
- poi excel导入导出
pom <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artif ...
- Quartz:不要重复造轮子,一款企业级任务调度框架。
背景 第一次遇到定时执行某些任务的需求时,很多朋友可能设计了一个小类库,这个类图提高了一个接口,然后由调度器调度所有注册的接口类型,我就是其中之一,随着接触的开源项目越来越多,我的某些开发习惯受到了影 ...