从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 ...
随机推荐
- POJ-3131-Cubic Eight-Puzzle(双向BFS+哈希)
Description Let's play a puzzle using eight cubes placed on a 3 × 3 board leaving one empty square. ...
- 如何制作一款HTML5 RPG游戏引擎——第二篇,烟雨+飞雪效果
今天我们来实现烟雨+飞雪效果.首先来说,一款经典的RPG游戏难免需要加入天气的变化.那么为了使我们的RPG游戏引擎更完美,我们就只好慢慢地实现它. 本文为该系列文章的第二篇,如果想了解以前的文章可以看 ...
- visual studio NuGet
http://www.cnblogs.com/dudu/archive/2011/07/15/nuget.html 首先打开程序包管理器控制台:工具→Nuget程序包管理器→程序包管理器控制台 Ins ...
- 基于docker的gitlab+gitlabrunner+ansible自动部署
系统架构图 网络架构 一.安装docker,确保hostname没有问题 ,查看/etc/hostname./etc/hosts. https://docs.docker.com/engine/ins ...
- Zen cart 根据数量打折插件
Quantity Discounts 可以根据顾客购买多少来打折,很不错. 假如顾客买了3个以上的产品,就给他10%折扣,设置如下: Turn On Quantity Discount 1. In t ...
- 从u-boot的编译结果中提取include目录
ac@DESKTOP-BJ1MJGM:~/u-boot-2019.01/spl$ arm-linux-gnueabihf-objdump -g u-boot-spl | awk '/The Direc ...
- Visual studio插件 Reshaper--- 常用快捷键
快速修复 alt+enter (alt+enter唤出快速修复面板,上下方向键进行选择,再次敲击enter键确定修改) 跳转到对象声明 ctl+鼠标左键 重构-重命名(ctl+r+r) esc键退出 ...
- 关于jQuery获得表单radio类型输入框的选中值
var item=$("input[name='w1']checked").val(); 下面这句,问题解决(加上[type='radio']:): var item=$(&quo ...
- mycat实战之性能测试
1.安装性能监控工具 1.1 nmon 安装nmon de >#下载地址 http://nmon.sourceforge.net/pmwiki.php?n=Site.Download nmon1 ...
- 多媒体文件格式分析 MP3文件结构及编解码流程
多媒体文件格式分析 http://blog.csdn.net/taniya001/article/details/7962864 多媒体文件格式分析 MP3文件结构及编解码流程 http://www. ...