Java同步容器与并发容器
2016-08-29 18:15
337 查看
Java容器
Java提供了很多容器类,方便用户使用。关键接口图如下(图片来源自The Java™ Tutorials),Collection——集合框架结构的根节点。Java并没有提供该接口的具体实现,但是提供了Collection子接口,比如Set,List的具体实现。
Set——没有重复元素的集合。
List——有序的集合(或称为序列)。可以包括重复元素。
Queue——用于保存多个待处理的元素。典型地(但非必须),满足FIFO(先进先出)规则。
Deque——保存多个待处理的元素。支持先进先出(FIFO)和先进后出(LIFO)。双向,元素可以在两个方向添加或删除。
Map——将键(key)映射到值(value)的结构。不能包含相同的key,每个key至多映射到一个value。
同步容器类
我们平时用的ArrayList,Queue,HashMap,都不是同步安全的。如果我们在多个线程中这些类的实例,就可能发生线程干扰或内存一致性错误。我们可以使用同步访问来解决这个问题,但是Java已经帮我们实现了,这就是接下来的同步容器类。同步容器类包括:
Vector和Hashtable,还有继承Vector的Stack类。
Collections.synchronizedXxx等工厂方法创建的类。
这些类实现线程安全的方法是:将它们的成员变量设置为私有(状态封装),并对每个公有方法都进行同步,使得每次只有一个线程能访问类的实例。
我们可以方便得使用这些同步容器来实现多个线程同步访问。但是并不意味同步容器可以完全保证线程安全。考虑以下的例子,
public static Object getLast(Vector vector) { int lastIndex = vector.size() - 1; return vector.get(lastIndex); } public static void deleteLast(Vector vector) { int lastIndex = vector.size() - 1; vector.remove(lastIndex); }
这两个代码都会执行“先检查再运行”操作。先获得向量的大小,然后根据结果来得到或删除最后一个元素。如果这两个代码运行在两个线程中,会发生以下的执行序列,
getLast得到向量大小,为10,
deleteLast得到向量大小,为10,
deleteLast删除最后一个元素,此时向量的大小为9
getLast得到最后一个元素,get(9),但是由于deleteLast将最后一个元素删除,此时长度为9,所以此时会出错。
容器上常见的复合操作包括:迭代、跳转以及条件运算,例如“没有则添加”。在同步容器中,这些复合操作是线程安全的,但是在其他线程并发地修改容器时,就会发生意料之外的行为。比如上面的例子。
我们可以通过客户端加锁来解决该问题,使得getLast和deleteLast成为原子操作,确保vector的大小在调用size和get之间不会发生变化,示例代码如下:
public static Object getLast(Vector vector) { synchronized (vector) { int lastIndex = vector.size() - 1; return vector.get(lastIndex); } } public static void deleteLast(Vector vector) { synchronized (vector) { int lastIndex = vector.size() - 1; vector.remove(lastIndex); } }
并发容器类
同步容器将所有对容器状态的访问都串行化,来实现线程安全性。这种方法的代价是严重降低并发性,当多个线程竞争容器的锁时,吞吐量将严重降低。Java 提供了多种并发容器来改善同步容器的性能。另外,并发容器是针对多个线程并发访问设计的。
替代Map的ConcurrentHashMap
替代SortedMap的ConcurrentSkipListMap
替代SortedSet的ConcurrentSkipListSet
替代List的CopyOnWriteArrayList
ConcurrentLinkedQueue,先进先出队列
BlockingQueue,货站了Queue,支持可阻塞的插入和获取等操作
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序