【Java集合】除了Vector,还有另一个提供线程安全的List是什么? |
您所在的位置:网站首页 › java常用线程安全类 › 【Java集合】除了Vector,还有另一个提供线程安全的List是什么? |
前言
金三银四,势在必得。我自信又有点紧张地走进了面试现场。 面试官:“我们先聊点Java基础吧,除了Vector,还有另一个提供线程安全的List是什么?”。 我:“我知道可以通过Collections.synchronizedList()方法,将线程不安全的List转为线程安全。" 面试官笑着说:“那么Collections.synchronizedList()的实现原理是什么?“。 我:“额…这个我不是很清楚”。 无疑,这这触及到了我的知识盲点。 面试官:“你可以了解一下SynchronizedList,没事,我们到下一个问题哈…" 面试结束后,我留下了学海无涯的泪水… 对于这个问题,我们的回答思路可以是这样: SynchronizedList是什么呢?分析Vector与SynchronizedList之间的区别是什么?总结Vector和SynchronizedList之间的区别。(若文章有不正之处,或难以理解的地方,请多多谅解,欢迎指正) SynchronizedList是什么?在了解SynchronizedList之前,让我们先看看SynchronizedList在什么位置: 可以看到,将线程不安全的List转为线程安全的Collections.synchronizedList()方法,是通过生成SynchronizedList对象来实现的: static List synchronizedList(List list, Object mutex) { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList(list, mutex) : new SynchronizedList(list, mutex)); } 分析Vector与SynchronizedList之间的区别是什么?上文我们知道,SynchronizedList是java.util.Collections的静态内部类,那么Vector呢? Vector的实现: public void add(int index, E element) { insertElementAt(element, index); } public synchronized void insertElementAt(E obj, int index) { modCount++; if (index > elementCount) { throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount); } ensureCapacityHelper(elementCount + 1); System.arraycopy(elementData, index, elementData, index + 1, elementCount - index); elementData[index] = obj; elementCount++; } private void ensureCapacityHelper(int minCapacity) { // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }可以看到Vector的insertElementAt()方法使用了synchronized关键字来实现线程安全。不过这段代码的操作好面熟啊。是的,其实Vector与ArrayList除了线程安全方面有所不同,两者之间的代码都很相似,有兴趣的朋友可以看这篇文章:【Java集合】ArrayList的使用及原理。 我们来看看ArrayList的add()方法代码,除了没有synchronized修饰方法,还真的很相似: public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } private void rangeCheckForAdd(int index) { if (index > size || index = elementCount) throw new ArrayIndexOutOfBoundsException(index); E oldValue = elementData(index); int numMoved = elementCount - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--elementCount] = null; // Let gc do its work return oldValue; }ArrayList的实现: public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work return oldValue; }通过以上两段代码的比对,可以看到除了Vector的remove()方法使用了synchronized关键字来实现线程安全之外,二者的实现十分相似。 总结Vector与SynchronizedList之间的不同在总结之前,我们先回顾一下,Vector线程同步是通过同步方法来实现,SynchronizedList线程同步是通过同步代码块来实现,我们先区分一下这两种同步方式。 同步代码块在锁定的范围上可能比同步方法要小,但一般锁的范围大小和性能是成反比的。同步块可以更加精准地控制锁的作用域,而同步方法的锁的作用域是整个方法。同步代码块可以选择对哪个对象加锁,但是同步方法只能给this对象加锁。目前为止,我们可以看到Vector与SynchronizedList之间的不同在于: 扩容机制:Vector的扩容机制是固定的,而SynchronizedList可以根据出传入List的不同,适配不同List的扩容规则。锁:SynchronizedList可以指定锁定的对象。但其实还有两点我们忽略了: SynchronizedList中的listIterator和listIterator(int index)并没有做同步处理,而Vector却对它们上了锁,也就是说在使用SynchronizedList进行遍历的时候要手动加锁。将继承了List类的子类转换成SynchronizedList,是不需要改变它的底层数据结构,可以直接使用它本身的方法。而Vector底层结构就是使用数组实现的,所以Vector不能像SynchronizedList那样适配其他List类。所以SynchronizedList和Vector之间最主要的区别在于: SynchronizedList有很好的兼容能力,无需改变List类的子类的数据结构,就可以将它们转换成线程安全的类,而Vector不具备这种能力。SynchronizedList进行遍历时要手动进行同步处理,但Vector的遍历方法是线程安全的。SynchronizedList可以指定锁定的对象,但是Vector的锁定范围是方法。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |