从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 ...
随机推荐
- HTTP来源地址
HTTP来源地址(referer,或HTTP referer),是HTTP表头的一个字段,用来表示从哪儿链接到目前的网页,采用的格式是URL. 换句话说,借着HTTP来源地址,目前的网页可以检查访客从 ...
- OCR技术浅探 : 文字定位和文本切割(2)
文字定位 经过前面的特征提取,我们已经较好地提取了图像的文本特征,下面进行文字定位. 主要过程分两步: 1.邻近搜索,目的是圈出单行文字: 2.文本切割,目的是将单行文本切割为单字. 邻近搜索 我们可 ...
- python学习笔记(五)os、sys模块
一.os模块 print(os.name) #输出字符串指示正在使用的平台.如果是window 则用'nt'表示,对于Linux/Unix用户,它是'posix'. print(os.getcwd( ...
- 从原型链看DOM--Element类型
Element类型用于表现XML或HTML元素,提供对元素标签名,子节点及特性的访问.原型链的继承关系为 某节点元素.__proto__->(HTML某元素Element.prototype)- ...
- php微信支付回调验证
//字典排序拼接字符串 function getWxPaySignature($arr){ ksort($arr); $str = ''; foreach ($arr as $k=>$a){ $ ...
- 洛谷 P4211 [LNOI2014]LCA (树链剖分+离线)
题目:https://www.luogu.org/problemnew/solution/P4211 相当难的一道题,其思想难以用言语表达透彻. 对于每个查询,区间[L,R]中的每个点与z的lca肯定 ...
- SqlHelper简单实现(通过Expression和反射)6.Providor模式(工厂+策略)可配置数据库选择
基本思想,将MsSqlDbUtility和MySqlDbUtility设计成单例模式,通过App.config或Web.config进行默认的数据库设置,然后通过DbUtilityFactory获取D ...
- 通过Java编码获取String分行字符串的内容
代码案列: import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException ...
- Ubuntu16.04 sever 安装
插入U盘,开机有两个USB启动方式(传统模式和UEFI模式): 启动快速,我选择了UEFI模式,跳过BIOS初始化. 用启动盘成功引导之后,出现下面的界面 选择安装语言:中文(简体) 默认第一项:安装 ...
- AVAudioSession(3):定制 Audio Session 的 Category
本文转自:AVAudioSession(3):定制 Audio Session 的 Category | www.samirchen.com 本文内容主要来源于 Working with Catego ...