并发库应用之十三 & 并发集合类的应用
传统集合实现同步的问题
举了一个例子:Map集合线程不同步导致的问题。
解决办法:使用同步的Map集合
使用集合工具类中的方法将不同步的集合转为同步的Collections.synchronizedMap(newMap())这个方法返回一个同步的集合
public static <K, V> Map<K, V> synchronizedMap(Map<K, V> m) {return newSynchronizedMap<K, V>(m);}
SynchronizedMap类相当于一个代理类,通过查看源代码发现:该类中的所有方法都是直接返回-->原Map集合方法调用后的结果,只是将返回结果的代码放在了同步代码块中以实现同步,构造是将同步锁默认置为当前对象。
HashSet与HashMap的关系与区别:
HashSet是单列的,HashMap是双列的(键值对)
关系:HashSet内部使用的是HashMap中的键,不考虑值。查看HashSet的源代码发现其内部就是用HashMap实现的,只是没有使用HashMap的V,只使用了它的K。
JDK1.5中提供了并发 Collection:提供了设计用于多线程上下文中的 Collection 实现:
- ConcurrentHashMap
- ConcurrentSkipListMap 类似于TreeMap
- ConcurrentSkipListSet 类似于TreeSet
- CopyOnWriteArrayList
- CopyOnWriteArraySet
使用总结:
当期望许多线程访问一个给定 collection 时,ConcurrentHashMap 通常优于同步的 HashMap,ConcurrentSkipListMap 通常优于同步的 TreeMap。当期望的读数和遍历远远大于列表的更新数时,CopyOnWriteArrayList优于同步的ArrayList。
ConcurrentSkipListMap<K,V> 映射可以根据键的自然顺序进行排序,也可以根据创建映射时所提供的 Comparator 进行排序,具体取决于使用的构造方法。
ConcurrentSkipListSet<E> 一个基于 ConcurrentSkipListMap 的可缩放并发 NavigableSet 实现。set 的元素可以根据它们的自然顺序进行排序,也可以根据创建 set 时所提供的 Comparator 进行排序,具体取决于使用的构造方法
CopyOnWriteArrayList<E> 是ArrayList 的一个线程安全的变体,其中所有可变操作(add、set 等等)都是通过对底层数组进行一次新的复制来实现的。
这一般需要很大的开销,但是当遍历操作的数量大大超过可变操作的数量时,这种方法可能比其他替代方法更有效。在不能或不想进行同步遍历,但又需要从并发线程中排除冲突时,它也很有用。
CopyOnWriteArraySet<E> 对其所有操作使用内部 CopyOnWriteArrayList 的 Set。因此,它共享以下相同的基本属性:
它最适合于具有以下特征的应用程序:set 大小通常保持很小,只读操作远多于可变操作,需要在遍历期间防止线程间的冲突。它是线程安全的。 因为通常需要复制整个基础数组,所以可变操作(add、set 和 remove 等等)的开销很大。 迭代器不支持可变 remove 操作。 使用迭代器进行遍历的速度很快,并且不会与其他线程发生冲突。在构造迭代器时,迭代器依赖于不变的数组快照。
传统集合中存在的其它问题:对集合迭代时,不能对集合中的元素进行修改(添加、删除……),Java5中提供的并发集合就解决了这个问题。具体详情内容可以参看我上一篇博客:并发库应用之十二 & 常用集合问题汇总
并发库应用之十三 & 并发集合类的应用的更多相关文章
- 并发库应用之十二 & 常用集合问题汇总
1. List遍历时修改报错 别的先什么都不说,直接上代码看看就知道了: public class ListTest { public static void main(String[] args) ...
- Java中的线程--并发库中的集合
线程中的知识点基本都已经学完了,看看Java5并发库中提供的集合... 一.可堵塞队列 队列包含固定长度的队列和不固定长度的队列 ArrayBlockQueue中只有put()方法和take()方法才 ...
- Java线程新特征——Java并发库
一.线程池 Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定 ...
- Java多线程与并发库高级应用-java5线程并发库
java5 中的线程并发库 主要在java.util.concurrent包中 还有 java.util.concurrent.atomic子包和java.util.concurrent.lock子包 ...
- java并发库_并发库知识点整理
并发库(java.util.concurrent)中的工具数不胜数,那么我们梳理一下线程并发库中重要的一些常用工具: 1.
- 线程高级应用-心得8-java5线程并发库中同步集合Collections工具类的应用及案例分析
1. HashSet与HashMap的联系与区别? 区别:前者是单列后者是双列,就是hashmap有键有值,hashset只有键: 联系:HashSet的底层就是HashMap,可以参考HashSe ...
- 线程高级应用-心得5-java5线程并发库中Lock和Condition实现线程同步通讯
1.Lock相关知识介绍 好比我同时种了几块地的麦子,然后就等待收割.收割时,则是哪块先熟了,先收割哪块. 下面举一个面试题的例子来引出Lock缓存读写锁的案例,一个load()和get()方法返回值 ...
- 线程高级应用-心得4-java5线程并发库介绍,及新技术案例分析
1. java5线程并发库新知识介绍 2.线程并发库案例分析 package com.itcast.family; import java.util.concurrent.ExecutorServi ...
- java--加强之 Java5的线程并发库
转载请申明出处:http://blog.csdn.net/xmxkf/article/details/9945499 01. 传统线程技术回顾 创建线程的两种传统方式: 1.在Thread子类覆盖的r ...
随机推荐
- 如何手动实现C语言中的字符串操作
学了字符串操作,很多人也许学了大概知道怎么用,但是太久没用就忘了,恰恰这是找软件工程师或者嵌入式工程师以及C,C++相关的笔试面试必考的题目!接下来我们来看看如何手动实现这些相关的函数. 废话不多说, ...
- 【Visual C++】游戏编程学习笔记之二:定时器的使用
本系列文章由@二货梦想家张程所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44195831 作者:ZeeCode ...
- LIRe 源代码分析 6:检索(ImageSearcher)[以颜色布局为例]
===================================================== LIRe源代码分析系列文章列表: LIRe 源代码分析 1:整体结构 LIRe 源代码分析 ...
- Android控件属性android:visibility的invisible与gone的区别
"invisible" : 不可见 "gone" : 隐 藏 主要区别在于控件设置了invisible后控件不可见,但是保留了控件在界面上的空间, ...
- Leetcode_237_Delete Node in a Linked List
本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/47334649 Write a function to de ...
- JSP 知识基本
from:http://blog.csdn.net/caipeichao2/article/details/38589293 more:http://www.2cto.com/kf/web/jsp/4 ...
- Android绘图机制(四)——使用HelloCharts开源框架搭建一系列炫酷图表,柱形图,折线图,饼状图和动画特效,抽丝剥茧带你认识图表之美
Android绘图机制(四)--使用HelloCharts开源框架搭建一系列炫酷图表,柱形图,折线图,饼状图和动画特效,抽丝剥茧带你认识图表之美 这里为什么不继续把自定义View写下去呢,因为最近项目 ...
- java的双缓冲技术
Java的强大特性让其在游戏编程和多媒体动画处理方面也毫不逊色.在Java游戏编程和动画编程中最常见的就是对于屏幕闪烁的处理.本文从J2SE的一个再现了屏幕闪烁的Java Appilication简单 ...
- Linux Framebuffer驱动剖析之一—软件需求
嵌入式企鹅圈将以本文作为2015年的终结篇,以回应第一篇<Linux字符设备驱动剖析>.嵌入式企鹅圈一直专注于嵌入式Linux和物联网IOT两方面的原创技术分享,稍后会发布嵌入式企鹅圈的2 ...
- javascript中正则表达式和ruby中的一点差异
看到一个例子,不过这个例子中正则表达式的格式貌似是错的: Function.prototype.get_name = function(){ return this.name || this.toSt ...