List相关类源码解析之从Vector学习装饰模式
- 关于Vector, Vector源码的话,和ArrayList基本差不多, 因此没必要再讲一次。实际上, 我基本没用过Vector。 只是在看ArrayList的时候大概浏览了一下Vector源码。
- 这里要说的是 Vector的由来, 加深对装饰模式的理解.
- 思考一下,在没有 current包和Vector之前。我们要如何实现List的线程安全? 那时候也没有锁如ReentrantLock的, 如何简单的利用已有的资源快速实现一个线程安全的List呢?
- 想一想。 好像设计模式,有谈到如何增强一个类。即装饰模式, 类图如下:
- 使用装饰模式,我们简单对 ArrayList进行同步增强。 对List相关的操作, 加上synchronized , 就有了同步的功能。 这样子, 我们就知道, Vector是怎么来的了。
- 当然,看源码,我们可以知道。 Vector 不是对 ArrayList或List的 装饰(不是通过持有List的引用)来增强。 而是继承实现了List,从这里我们也可以知道另外一点,要增强一个类,还有继承的方式。
- Vector但是和 ArrayList 非常相似。 不同的地方就是 Vector某些对elementData操作的方法,直接加了 synchronized, 简陋实现了线程安全。
- 这也是Vector现在比较少用的原因,
synchronized
是一个悲观锁,只是简单限制了只能一个线程进入代码, 从而保证线程安全,但同时它效率也比较差。 - 那么如果我们要自己实现Vector的效果的话,其实没有必要像Vector那样, 把ArrayList重复一遍, 只要对ArrayList进行装饰增强既可以达到目的。
- 事实上, JAVA里也对这种方式进行了实现。 那就是
Collections.synchronizedXXXX
方法。 这些方法实际上就是对集合的某些方法进行简单装饰增强, 返回集合的同步装饰实现类,简单在各个操作增加了同步synchronized。
- 例如,
Collections.synchronizedList(List list)
返回了 List的装饰类SynchronizedList
或SynchronizedRandomAccessList
. 源码如下:
public static <T> List<T> synchronizedList(List<T> list) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list) :
new SynchronizedList<>(list));
}
例如SynchronizedList源码为
static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
private static final long serialVersionUID = -7754090372962971524L;
final List<E> list;
SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
SynchronizedList(List<E> list, Object mutex) {
super(list, mutex);
this.list = list;
}
public boolean equals(Object o) {
if (this == o)
return true;
synchronized (mutex) {return list.equals(o);}
}
public int hashCode() {
synchronized (mutex) {return list.hashCode();}
}
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
public E set(int index, E element) {
synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {
synchronized (mutex) {return list.remove(index);}
}
public int indexOf(Object o) {
synchronized (mutex) {return list.indexOf(o);}
}
public int lastIndexOf(Object o) {
synchronized (mutex) {return list.lastIndexOf(o);}
}
public boolean addAll(int index, Collection<? extends E> c) {
synchronized (mutex) {return list.addAll(index, c);}
}
public ListIterator<E> listIterator() {
return list.listIterator(); // Must be manually synched by user
}
public ListIterator<E> listIterator(int index) {
return list.listIterator(index); // Must be manually synched by user
}
public List<E> subList(int fromIndex, int toIndex) {
synchronized (mutex) {
return new SynchronizedList<>(list.subList(fromIndex, toIndex),
mutex);
}
}
/**
* SynchronizedRandomAccessList instances are serialized as
* SynchronizedList instances to allow them to be deserialized
* in pre-1.4 JREs (which do not have SynchronizedRandomAccessList).
* This method inverts the transformation. As a beneficial
* side-effect, it also grafts the RandomAccess marker onto
* SynchronizedList instances that were serialized in pre-1.4 JREs.
*
* Note: Unfortunately, SynchronizedRandomAccessList instances
* serialized in 1.4.1 and deserialized in 1.4 will become
* SynchronizedList instances, as this method was missing in 1.4.
*/
private Object readResolve() {
return (list instanceof RandomAccess
? new SynchronizedRandomAccessList<>(list)
: this);
}
}
观察几个主要的 方法, 如add 、 remove, 是不是发现, 只是在调用传入list的 add和remove,只是在里面加了锁,实现线程安全。
说明:
这里的Vector和Collections.synchronizedXXXX
例子,一个是加深对List的了解,另一个作为学习装饰模式一个例子。而不是为了使用 Vector或者List来做线程安全的List类。 在没有conrrent包的实现的时候,这种做法可以接受的,但是在conrrent出现之后,就不该使用这样的了。