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的装饰类 SynchronizedListSynchronizedRandomAccessList. 源码如下:
  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出现之后,就不该使用这样的了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值