从SynchronizedCollection说起
SynchronizedCollection简介
SynchronizedCollection是Collections下所有现场安全集合的父类,并发安全集合可以分为三类,一种是比较老的实现,例如vector,一种是concurrent包下的,另外一种就是SynchronizedCollection。他是通过对并发不安全的集合进行包装,使得线程安全。
实现介绍
上面也说了,他是通过对并发不安全的集合进程包装的。思想上就是加了一个object锁,然后在每个方法上加入锁的逻辑。
static class SynchronizedCollectionimplements Collection, Serializable {
final Collectionc; // Backing Collection
final Object mutex; // Object on which to synchronize
SynchronizedCollection(Collectionc, Object mutex) {
this.c = Objects.requireNonNull(c);
this.mutex = Objects.requireNonNull(mutex);
}
....
}
SynchronizedCollection有两个成员变量,一个是被包装的集合对象c,一个是用来作为锁的对象mutex。集合对象和锁对象都可以通过构造函数传入。
大家如果看过vector的实现的话,大概明白接下来的实现手段了,就是加锁!
public int size() {
synchronized (mutex) {return c.size();}
}
public boolean isEmpty() {
synchronized (mutex) {return c.isEmpty();}
}
public boolean contains(Object o) {
synchronized (mutex) {return c.contains(o);}
}
public Object[] toArray() {
synchronized (mutex) {return c.toArray();}
}
publicT[] toArray(T[] a) {
synchronized (mutex) {return c.toArray(a);}
}
是不是看了实现的你也是微微一下,这里就是通过synchronized 加锁mutex。然后在代码块里执行原来的集合的方法,由于每个方法都被加上了锁,所以集合也成为了并发安全的集合。
安全性依靠的就是集合被覆写,如果没有被覆写,那么线程安全性也就不保证了。很多人也很好奇,这都是包装安全了,为啥还会这么说。
下面就展示一个例外。
public Iteratoriterator() {
return c.iterator(); // Must be manually synched by user!
}
iterator方法没有被覆写!也就是说使用迭代器迭代的时候,线程是不安全的,所以这个方法的也加了注释,需要用户加同步。
很多时候大家的第一反应就是给iterator加synchronized 的就可以。但是真的是这样吗?
我们来推演一下,如果在iterator方法上加锁,那么确实保证了iterator方法是线程安全的,在并发的情况下,只会有一个线程操作成功,成功获取到iterator对象。但是接下来呢,我们要拿到iterator对象进行迭代,此时如果集合有增删操作是可以的,因为iterator对象的操作完全没有锁竞争。此时迭代就会出错。
装饰者模式
SynchronizedCollection这种通过实现Collection接口,然后自己把接口的方法都实现了一遍,并且使用了组合的方式,对每个方法增加了新的功能,最后还返回接口对象,面向接口编程。这就是典型的装饰者模式。
为了增加新的功能,不断的继承接口,实现自己的新逻辑,而且对调用端屏蔽了操作。如果说在增加一个需求,就是需要一个集合操作完之后就删除一个元素。那么只要实现Collection接口,对每个方法的调用都做一个删除的操作,并且执行传入的集合对象就可以了,在生成对象的时候,不断的构造对象传入。如果功能不需要了,例如不需要线程安全的需求了,那么只要在生成对象的时候,直接去掉SynchronizedCollection就可以了。
装饰者模式的优点就是对外面向接口,对调用者屏蔽细节。然后功能拆分比较细,可以进行比较灵活的组装。
iterator的问题,其实也是装饰者模式的弊端,就是他对包装者的功能扩展是有一定限制的。他可以对他包装的对象进行扩展,但是并不能对包装对象里依赖的对象进行太多的干预。
java中装饰者模式的应用
除了上面的SynchronizedCollection。java中另外一个典型的案例就是io。
java的io是可以不停的功能扩展的。
FileInputStream是基础的字节io
InputStreamReader可以对FileInputStream进行功能扩充
BufferedReader对Reader可以再进程扩充
其实大家使用的时候的一些缺点也暴露出来了,就是功能扩充的限制问题,我们一旦装饰到BufferedReader,就不会再去使用read方法了,主要使用readLine这个功能了,其实接口并没有这个方法,所以我们使用io的时候已经不再是面向接口了,更多的是面向了具体的实现,因为在文件的场景下。接口并不能彻底抽象全部功能,他只能有共有的。
总结
java中有两个地方使用了装饰者模式,io,SynchronizedCollection。
SynchronizedCollection对每个方法进行了功能的扩充,但是对包装类里的成员变量不能控制。
io增加了功能,但是功能有更多的特性,最后反而是面向了实现类编程。
装饰者模式的好处是灵活,功能扩展方便。坏处就是功能扩展有限制,一个限制在接口,一个限制在被装饰者内部的成员变量。
从SynchronizedCollection说起的更多相关文章
- 用Collections.synchronizedCollection创建线程安全的集合、列表。。。
Collection c=Collections.synchronizedCollection(new ArrayList()); List list=Collections.synchronized ...
- java - 并发集合 Vector、synchronizedCollection、CopyOnWriteArrayList之间的区别。
概要 JDK中提供ArrayList集合方便我们对集合内元素进行增删改查,但是ArrayList为了能够在单线程中快速进行操作其设计并不支持多线程进行操作.ArrayList在多线程环境下可能会产生j ...
- 计算机程序的思维逻辑 (54) - 剖析Collections - 设计模式
上节我们提到,类Collections中大概有两类功能,第一类是对容器接口对象进行操作,第二类是返回一个容器接口对象,上节我们介绍了第一类,本节我们介绍第二类. 第二类方法大概可以分为两组: 接受其他 ...
- Collection集合
一些关于集合内部算法可以查阅这篇文章<容器类总结>. (Abstract+) Collection 子类:List,Queue,Set 增: add(E):boolean addAll(C ...
- C#泛型方法解析
C#2.0引入了泛型这个特性,由于泛型的引入,在一定程度上极大的增强了C#的生命力,可以完成C#1.0时需要编写复杂代码才可以完成的一些功能.但是作为开发者,对于泛型可谓是又爱又恨,爱的是其强大的功能 ...
- Java Hashtable的实现
先附源码: package java.util; import java.io.*; /** * This class implements a hash table, which maps keys ...
- Java基础应用
Java集合类解析 List.Map.Set三个接口,存取元素时,各有什么特点? List 以特定次序来持有元素,可有重复元素.Set 无法拥有重复元素,内部排序.Map 保存key-value值,v ...
- Java集合面试题
1.Java集合框架是什么?说出一些集合框架的优点? 每种编程语言中都有集合,最初的Java版本包含几种集合类:Vector.Stack.HashTable和Array.随着集合的广泛使用,Java1 ...
- System.Collections.Generic的各容器类的用法
演示System.Collections.Generic的各容器类的用法. 包括:Dictionary,KeyValuePair,SortedDic tionary,SortedList,HashSe ...
随机推荐
- 【开发者笔记】解析具有合并单元格的Excel
最近公司让做各种数据表格的导入导出,就涉及到电子表格的解析,做了这么多天总结一下心得. 工具:NOPI 语言:C# 目的:因为涉及到导入到数据库,具有合并单元格的多行必然要拆分,而NPOI自动解析的时 ...
- Lepus_天兔的安装
一.安装平台 Centos 32位 二.依赖软件 依赖软件包:mysql.php.apache集成在xampp中,python,MySQLdb模块安装包在lepus安装包目录中 以下标红软件是必须安装 ...
- JPG PNG GIF 的优缺点
pg/jpeg:优点:体积比png小,打开速度比png快缺点:属于有损压缩,每次保存都会产生数据损失(jpeg artifacts), 故不适合用于多次编辑保存.压缩率过高图像会失真PS:网络上最最常 ...
- libevent基础知识
在线手册 • 官方网站:http://libevent.org/ • 官方手册:http://www.wangafu.net/~nickm/libevent-book/ • 官方下载:http://s ...
- linux rm指定的文件
如何删除一个目录下的除了想要的文件之外的所有文件 rm `ls | grep -v "aa"` Linux下 报错“命令参数列表过长”,在用mv命令一次移动3万多个文件时失败了,原 ...
- TWebBrowser: Determine when a page with Frames is completed
TWebBrowser: Determine when a page with Frames is completed 6 comments. Current rating: (3 votes). L ...
- __new__方法以及TypeError: object() takes no parameters的处理
一些python书或博客将类中的__init__方法称为构造函数,而实际上这种说法是不严格的,因为创建实例的方法是__new__,实例初始化的方法是__init__.__new__方法会返回一个实例, ...
- ruby中的作用域
作用域(scope)指的是变量的可达性或可见性.不同类型的变量有不同的作用域规则.与self类似,作用域在程序的执行过程中也在不断的变化,也可以根据上下文推断出"谁在什么作用域中" ...
- java内存回收
java中引用类型 强引用 Persnon p = new Person(); 当指向Person对象的引用计数为0时,Person对象才能被垃圾回收器回收. 软引用 SoftReference&l ...
- Druid学习之路 (三)Druid的数据源和段
作者:Syn良子 出处:https://www.cnblogs.com/cssdongl/p/9703204.html 转载请注明出处 Druid的数据源和分段 Druid的数据存储在"Da ...