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 ...
随机推荐
- PAT (Advanced Level) 1083. List Grades (25)
简单排序. #include<cstdio> #include<cstring> #include<cmath> #include<vector> #i ...
- flexpaper二次开发
1.首先下载FlexPaper的源码.下载地址 2.本人不懂flash,只是百度下,然后自己瞎弄弄的.我用的flash build 4.5 提供个key:1499-4181-9296-6452-299 ...
- [Unity]Unity开发NGUI代码实现ScrollView(滚动视图)
Unity开发NGUI代码实现ScrollView(滚动视图) 下载NGUI包 导入NGUI3.9.1版本package 链接: http://pan.baidu.com/s/1mgksPBU 密码: ...
- POJ 2395 Out of Hay
这个问题等价于求最小生成树中权值最大的边. #include<cstdio> #include<cstring> #include<cmath> #include& ...
- 8、手把手教你Extjs5(八)自定义菜单2
这一节来定义另外三种类型的菜单类.首先定义菜单按钮类.文件放于app/view/main/region目录下面,文件名为ButtonMainMenu.js. /** * 显示在顶部的按钮菜单,可以切换 ...
- Solr 按照得分score跟指定字段相乘排序
sort=product([you_field],query($q)) desc
- C# GridView Edit & Delete, 点击Delete的时候弹出确认框
1. 使用GridView自带属性ShowEditButton和ShowDeleteButton,均设为True <Columns> ... <asp:CommandField S ...
- iOS 之UICollectionView 之原理介绍
0. 简介 参考:支持重排的iOS9 UICollectionView 参考:http://www.cnblogs.com/langtianya/p/3902801.html 参考:http://ww ...
- STM8的中断系统以及外部中断详解
STM8具有最多32的中断系统,在中断的处理上类似于cortexm系列的芯片,首先是每个中断的向量都是固化在系统内部的,用户需要向相应的中断向量flash位置写入中断处理函数,其二,每个中断向量都具有 ...
- uCOS-iii 中定义的一些常量
uCOS-iii 中定义的一些常量 uCOS-iii 中有许多宏定义的量,这些量不需要全部记住是什么意思,因为在阅读代码的时候可以选中变量或宏定义然后右键查看定义,就可以知道它代表的什么意思.但是如果 ...