JDK1.8源码阅读系列之三:Vector
本篇随笔主要描述的是我阅读 Vector 源码期间的对于 Vector 的一些实现上的个人理解,用于个人备忘,有不对的地方,请指出~
先来看一下 Vector 的继承图: 可以看出,Vector 的直接父类是 AbstractList(已在JDK1.8源码阅读系列之一介绍过), 直接子类是 Stack(下一篇文章介绍)。
在 Vector 类源码中,我认为有以下几个地方值得注意:
1、Vector 类几乎对每一个独立操作(除 Iterator 相关方法)都实现了同步,即在每个方法上几乎都增加了 synchronized 关键字来实现线程间的同步。
2、Vector 扩容方法 grow()
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
可见 Vector 的扩容量是由 oldCapacity 与 capacityIncrement 共同决定的,capacityIncrement 是我们可控的一个参数,在构造方法中传入,即每次容量具体增加多少,如果我们在创建 Vector 对象是没有指定 capacityIncrement,则默认每次把容量增加为原来的二倍(不越界的情况下)。
3、Vector 类中的 subList()方法我认为值得注意,源码如下:
public synchronized List<E> subList(int fromIndex, int toIndex) {
return Collections.synchronizedList(super.subList(fromIndex, toIndex),
this);
}
可见 Vector 调用的是其父类 AbstractList 类中的 subList 方法,并利用 Collections.synchronizedList() 进行装饰,下面看下 Collections.synchronizedList() 方法:
public class Collections {
......
static <T> List<T> synchronizedList(List<T> list, Object mutex) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list, mutex) :
new SynchronizedList<>(list, mutex));
}
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 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);}
}
......
} ......
}
可见 Collections.synchronizedList() 方法中传入的两个参数 一个是用于底层数组操作的 list,一个是信号量,用于线程间同步。在 vector 类的 subList 方法中,我们传入的参数为 AbstractList 类 subList 方法产生的基于 vector 的 list(对此 list 上进行的操作都会反应到 vector 当中去),还有把 vector 作为信号量参数传入,之所以要把 vector 对象作为信号量,是因为产生的 subList 底层是基于 vector 的,对此 subList 上进行的同步操作应与 vector 上进行的同步操作条件相同,防止同步出现问题。
4、为什么java Vector
类被认为是一个遗留的,过时的或废弃的类?在并发操作时,使用它是无效的吗?
Vector中对每一个独立操作都实现了同步,这通常不是我们想要的做法。对单一操作实现同步通常不是线程安全的(举个例子,比如你想遍历一个Vector实例。你仍然需要申明一个锁来防止其他线程在同一时刻修改这个Vector实例。如果不添加锁的话通常会在遍历实例的这个线程中导致一个ConcurrentModificationException
)同时这个操作也是十分慢的(在创建了一个锁就已经足够的前提下,为什么还需要重复的创建锁)当然,即使你不需要同步,Vector也是有锁的资源开销的。
总的来说,在大多数情况下,这种同步方法是存在很大缺陷的。正如Mr Brain Henk指出,你可以通过用Collections.synchronizedList
来装饰一个集合 ,事实上 ,Vector
将“可变数组”的集合实现与“同步每一个方法”结合起来的做法是另一个糟糕的设计。
各个装饰方法能够更明确的指示其关注的功能实现。
对于其子类 Stack ,也可使用双端队列Deque/ArrayDeque
来实现栈操作,比如:
public static void main(String[] args) {
Deque<Integer> deque = new ArrayDeque<>();
deque.push(1);
deque.push(2);
deque.push(3);
System.out.println(deque.peek());//返回栈顶元素 不删除
System.out.println(deque.size());
while (!deque.isEmpty()) {
System.out.println(deque.pop());
}
}
如果你觉得本篇文章对你有用的话,请随手点击推荐,让更多的人看到,感谢!
参考:https://github.com/giantray/stackoverflow-java-top-qa/blob/master/contents/why-is-java-vector-class-considered-obsolete-or-deprecated.md
JDK1.8源码阅读系列之三:Vector的更多相关文章
- JDK1.8源码阅读系列之四:HashMap (原创)
本篇随笔主要描述的是我阅读 HashMap 源码期间的对于 HashMap 的一些实现上的个人理解,用于个人备忘,有不对的地方,请指出- 接下来会从以下几个方面介绍 HashMap 源码相关知识: 1 ...
- JDK1.8源码阅读系列之一:ArrayList
本篇随笔主要描述的是我阅读 ArrayList 源码期间的对于 ArrayList 的一些实现上的个人理解,有不对的地方,请指出- 先来看一下 ArrayList 的继承图: 由图可以看出,Array ...
- JDK1.8源码阅读系列之二:LinkedList
本篇随笔主要描述的是我阅读 LinkedList 源码期间的对于 LinkedList 的一些实现上的个人理解,有不对的地方,请指出- 先来看一下 LinkedList 的继承图: 由于 Abstra ...
- 【Dubbo源码阅读系列】之远程服务调用(上)
今天打算来讲一讲 Dubbo 服务远程调用.笔者在开始看 Dubbo 远程服务相关源码的时候,看的有点迷糊.后来慢慢明白 Dubbo 远程服务的调用的本质就是动态代理模式的一种实现.本地消费者无须知道 ...
- 源码阅读系列:EventBus
title: 源码阅读系列:EventBus date: 2016-12-22 16:16:47 tags: 源码阅读 --- EventBus 是人们在日常开发中经常会用到的开源库,即使是不直接用的 ...
- Spring源码阅读系列总结
最近一段时间,粗略的查看了一下Spring源码,对Spring的两大核心和Spring的组件有了更深入的了解.同时在学习Spring源码时,得了解一些设计模式,不然阅读源码还是有一定难度的,所以一些重 ...
- SpringMVC源码阅读系列汇总
1.前言 1.1 导入 SpringMVC是基于Servlet和Spring框架设计的Web框架,做JavaWeb的同学应该都知道 本文基于Spring4.3.7源码分析,(不要被图片欺骗了,手动滑稽 ...
- 【合集】TiDB 源码阅读系列文章
[合集]TiDB 源码阅读系列文章 (一)序 (二)初识 TiDB 源码 (三)SQL 的一生 (四)INSERT 语句概览 (五)TiDB SQL Parser 的实现 (六)Select 语句概览 ...
- 【Dubbo源码阅读系列】服务暴露之远程暴露
引言 什么叫 远程暴露 ?试着想象着这么一种场景:假设我们新增了一台服务器 A,专门用于发送短信提示给指定用户.那么问题来了,我们的 Message 服务上线之后,应该如何告知调用方服务器,服务器 A ...
随机推荐
- YouKu iOS笔试题一
序言 最近收到某某同学将去youku的iOS笔试题的邮件,希望笔者能整理一下,并提供参考答案.笔者决定整理出来,并分享给大家.当然,与此同时,也想看看youku的笔试题到底有多难,也考考自己有多少料吧 ...
- JAVA中浅复制与深复制 - coolmist - ITeye技术网站
body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...
- python 利用 ogr 写入shp文件,数据格式
python 利用 ogr 写入 shp 文件, 定义shp文件中的属性字段(field)的数据格式为: OFTInteger # 整型 OFTIntegerList # 整型list OFTReal ...
- CentOS 5.8 x64 源码安装 samba-3.6.9
环境 CentOS 5.8 X64 wget http://www.samba.org/samba/ftp/stable/samba-3.6.9.tar.gz tar zxvf samb ...
- Linux进程实时IO监控iotop命令详解
介绍 Linux下的IO统计工具如iostat, nmon等大多数是只能统计到per设备的读写情况, 如果你想知道每个进程是如何使用IO的就比较麻烦. iotop 是一个用来监视磁盘 I/O 使用状况 ...
- 刷新UITableView
[from]http://www.superqq.com/blog/2015/08/18/ios-development-refresh-uitableview/ UITableView对于iOS开发 ...
- 简易的AJAX工具[转]
关键字: ajax 1.创建XMLHttpRequest对象的js文件 Ajax.js function Ajax(){ var xmlHttp=null; if(window.XMLHt ...
- 5)Javascript设计模式:extends模式
简单的方式 function Person() { this.name = 'person'; } Person.prototype.say = function() {}; function Chi ...
- pku2104
传送门:http://poj.org/problem?id=2104 题目大意:给定一个长度为N的数组{A[i]},你的任务是解决Q个询问.每次询问在A[l], A[l+1], ...... , A[ ...
- OpenCV点滴2
明天回家了-- 昨天去见了老师,去之前告诉自己不要紧张,去了后还是紧张了,语无伦次,很没礼貌--(不敢看老师的眼睛) 刚才妈打电话说让我早点回去,不知道为什么,在空荡荡的宿舍里听到妈的声音,眼泪会夺眶 ...