ConcurrentHashMap
        HashMap是线程不安全的,可以使用Collections.synchronizedMap(map)把一个不安全的map变成安全的,但是这里可以直接使用ConcurrentHashMap。
       ConcurrentHashMap是线程安全的的Hash表。对于多线程的操作,介于HashMap和HashTable之间。内部采用“锁分段”机制替代HashTable的独占锁,进而提高性能。
         一个ConcurrentHashMap由多个segment【默认16个】组成,每一个segment都包含了一个HashEntry数组的HashTable, 每一个segment包含了对自己的HashTable的操作,比如get,put,replace等操作,这些操作发生的时候,对自己的HashTable进行锁定。由于每一个segment写操作只锁定自己的HashTable,所以可能存在多个线程同时写的情况,性能无疑好于只有一个HashTable锁定的情况。
示例:
ConcurrentHashMap和HashMap在迭代过程中添加键值对的比较。

ConcurrentHashMap代码:

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; public class ConcurrentHashMapDemo {
public static void main(String[] args) {
ConcurrentMap<String, String> cmap = new ConcurrentHashMap<>();
cmap.put("1", "111");
cmap.put("2", "222");
cmap.put("3", "333");
cmap.put("4", "444");
System.out.println("原Map:" + cmap);
Iterator<String> iterator = cmap.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
if (key.equals("2")) {
cmap.put("new" + key, "new222");
}
}
System.out.println("修改后:" + cmap);
}
}

结果:

HashMap代码:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; public class HashMapDemo {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1", "111");
map.put("2", "222");
map.put("3", "333");
map.put("4", "444");
System.out.println("原Map:" + map);
Iterator<String> it = map.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
if (key.equals("2")) {
map.put("new" + key, "new222");
}
}
System.out.println("修改后:" + map);
}
}

结果:

查看输出,很明显ConcurrentHashMap可以支持向map中添加新元素,而HashMap则抛出了ConcurrentModificationException。查看异常堆栈记录,可以发现是下面这条语句抛出异常:

String key = it.next();

这就意味着新的元素在HashMap中已经插入了,但是在迭代器执行时出现错误。事实上,集合对象的迭代器提供快速失败(Fail-Fast)的机制,即修改集合对象结构或者元素数量都会使迭代器触发这个异常。

使用要点简单总结:
1、 get方法不涉及到锁,也就是说获得对象时没有使用锁;
2、put、remove方法要使用锁,但并不一定有锁争用,原因在于ConcurrentHashMap将缓存的变量分到多个Segment,每个Segment上有一个锁,只要多个线程访问的不是一个Segment就没有锁争用,就没有堵塞,各线程用各自的锁,ConcurrentHashMap缺省情况下生成16个Segment,也就是允许16个线程并发的更新而尽量没有锁争用;
3、Iterator对象的使用,不一定是和其它更新线程同步,获得的对象可能是更新前的对象,ConcurrentHashMap允许一边更新、一边遍历,也就是说在Iterator对象遍历的时候,ConcurrentHashMap也可以进行remove,put操作,且遍历的数据会随着remove,put操作产出变化。

CopyOnWriteArrayList
       ArrayList是线程不安全的,也可以使用 Collections.synchronizedList(list)变成线程安全的。这里也可以直接使用CopyOnWriteArrayList。
       CopyOnWriteArrayList是线程安全的,它内部持有了ReenTrantLock对象,它使用了一种叫写时复制的方法,当有新元素添加到CopyOnWriteArrayList时,先从原有的数组中拷贝一份出来,然后在新的数组做写操作,写完之后,再将原来的数组引用指向到新数组。而读的时候不加锁不阻塞,即在原版上读,这样就实现了读写的分离。
示例:
这里主要测试它的线程安全性,不再与ArrayList作比较。

import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList; public class CopyOnWriteArrayListDemo {
static CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
static {
list.add("111");
list.add("222");
list.add("333");
list.add("444");
} public static void main(String[] args) {
Test test = new Test();
for (int i = 0; i < 5; i++) {
new Thread(test).start();
}
} static class Test implements Runnable { @Override
public void run() {
synchronized (this) { Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.print(it.next() + " ");
}
System.out.println();
list.add("555");
}
}
}
}

结果:

CopyOnWriteArraySet
        CopyOnWriteArraySet与CopyOnWriteArrayList的用法基本相同,唯一注意的就是CopyOnWriteArraySet是不允许重复(唯一)的。
示例:
我们修改一下CopyOnWriteArrayList的示例来看一下

import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArraySet; public class CopyOnWriteArraySetDemo {
static CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();
static {
set.add("111");
set.add("222");
set.add("222");
set.add("333");
} public static void main(String[] args) {
Test test = new Test();
for (int i = 0; i < 5; i++) {
new Thread(test).start();
}
} static class Test implements Runnable { @Override
public void run() {
synchronized (this) { Iterator<String> it = set.iterator();
while (it.hasNext()) {
System.out.print(it.next() + " ");
}
System.out.println();
set.add("444");
}
}
}
}

结果:

Java多线程_并发容器ConcurrentHashMap/CopyOnWriteArrayList/CopyOnWriteArraySet的更多相关文章

  1. JAVA 多线程随笔 (三) 多线程用到的并发容器 (ConcurrentHashMap,CopyOnWriteArrayList, CopyOnWriteArraySet)

    1.引言 在多线程的环境中,如果想要使用容器类,就需要注意所使用的容器类是否是线程安全的.在最早开始,人们一般都在使用同步容器(Vector,HashTable),其基本的原理,就是针对容器的每一个操 ...

  2. 多线程之并发容器ConcurrentHashMap

    这部分内容转载自: http://www.haogongju.net/art/2350374 JDK5中添加了新的concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为同步 ...

  3. 多线程之并发容器ConcurrentHashMap(JDK1.6)

    简介 ConcurrentHashMap 是 util.concurrent 包的重要成员.本文将结合 Java 内存模型,分析 JDK 源代码,探索 ConcurrentHashMap 高并发的具体 ...

  4. 并发容器-ConcurrentHashMap,CopyOnWriteArrayList

    ConcurrentHashMap HashMap是线程非安全的,在多线程环境下,采用的是Fail-Fast快速失败机制,即当A线程在访问容器的时候,如果此时B线程修改了HashMap的结构,那么就会 ...

  5. Java编程的逻辑 (74) - 并发容器 - ConcurrentHashMap

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  6. JAVA多线程和并发基础面试问答(转载)

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

  7. [转] JAVA多线程和并发基础面试问答

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

  8. JAVA多线程和并发基础面试问答

    转载: JAVA多线程和并发基础面试问答 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对 ...

  9. 【多线程】JAVA多线程和并发基础面试问答(转载)

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

随机推荐

  1. LQB2013A05前缀判断

    上一道题,,,把if条件写错了,,,,找了半天的bug我都快哭了, 好了好了 看见这种填空题,先理解题意 然后把代码copy下来,把空格注释掉,然后运行到编译没有错. 再理一下它的思路 // // C ...

  2. PHP date_timestamp_get() 函数

    实例 返回今天的日期和时间的 Unix 时间戳: <?php$date=date_create();echo date_timestamp_get($date);?> 运行实例 » 定义和 ...

  3. luogu P1712 [NOI2016]区间 贪心 尺取法 线段树 二分

    LINK:区间 没想到尺取法. 先说暴力 可以发现答案一定可以转换到端点处 所以在每个端点从小到大扫描线段就能得到答案 复杂度\(n\cdot m\) 再说我的做法 想到了二分 可以进行二分答案 从左 ...

  4. 【python接口自动化】- logging日志模块

    前言:我们之前运行代码时都是将日志直接输出到控制台,而实际项目中常常需要把日志存储到文件,便于查阅,如运行时间.描述信息以及错误或者异常发生时候的特定上下文信息. logging模块介绍 ​ Pyth ...

  5. js跳转界面

    js页面跳转大全 所谓的js页面跳转就是利用javesrcipt对打开的页面ULR进行跳转,如我们打开的是A页面,通过javsrcipt脚本就会跳转到B页面.目前很多垃圾站经常用js跳转将正常页面跳转 ...

  6. python3.5 continue和break 项目:买房分期付款(2)

    #案例:买房分期付款24万(10年期限) i=1#定义年份sum1=0while i<=10: print("第",i,"年到了......") if i ...

  7. SpringCloud系列之服务容错保护Netflix Hystrix

    1. 什么是雪崩效应? 微服务环境,各服务之间是经常相互依赖的,如果某个不可用,很容易引起连锁效应,造成整个系统的不可用,这种现象称为服务雪崩效应. 如图,引用国外网站的图例:https://www. ...

  8. MySQL数据库高可用方案

    一.什么是高可用性: 高可用性=可靠性,它的本质就是通过技术和工具提高可靠性,尽可能长时间保持数据可用和系统运行,实现高可用性的原则,首先要消除单点故障,其次通过冗余机制实现快速恢复,还有就是实现容错 ...

  9. 3、Template Method 模板方法 行为型设计模式

    1.了解模板方法 1.1 模式定义 定义一个操作算法中的框架,而将这些步骤延迟加载到子类中. 它的本质就是固定算法框架. 1.2 解决何种问题 让父类控制子类方法的调用顺序 模板方法模式使得子类可以不 ...

  10. 使用cors完成跨域请求处理

    跨域的含义 同源策略以及其限制内容 同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS.CSFR等攻击.所谓同源是指"协议+域名+端口&quo ...