Vector线程安全,ArrayList非线程安全
http://baijiahao.baidu.com/s?id=1638844080997170869&wfr=spider&for=pc
Vector线程安全,ArrayList非线程安全

java的架构师技术栈
这篇文章开始介绍Vector。他和ArrayList有一些相似,其内部都是通过一个容量能够动态增长的数组来实现的。不同点是Vector是线程安全的。因为其内部有很多同步代码快来保证线程安全。为此,这篇文章,也会通过从源码的角度来分析一下Vector,并和ArrayList等其他集合容器进行一个对比分析。
OK,开始今天的文章。
一、认识Vector
Vector可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。不过,Vector的大小是可以增加或者减小的,以便适应创建Vector后进行添加或者删除操作。
为此我们先看一下Vector在整个java集合体系中的位置

上面这张图我们也会发现Vector和ArrayList是出于一个等级上面的,继承关系也和ArrayList一样。不过从宏观上只能看到在整个体系中的位置,现在我们从Vector来看看他的继承关系。

详细细节
现在我们就根据这张图来进行一个分析,Vector继承于AbstractList,实现了List、RandomAccess、Cloneable、 Serializable等接口。
(1)Vector 继承了AbstractList,实现了List接口。
(2)Vector实现了RandmoAccess接口,即提供了随机访问功能。
(3)Vector 实现了Cloneable接口,即实现克隆功能。
(4)Vector 实现Serializable接口,表示支持序列化。
Vector实现的这些接口,表示会有这样的能力。但是还有一点,就是Vector是线程安全的。下面我们从源码的角度来分析一下Vector是如何实现这些接口和保持线程安全的特性的。
二、源码分析Vector
(1)构造方法
Vector的构造方法一共有四个,因为四个都比较重要,所以在这里就给出四个
第一个: 创建一个空的Vector,并且指定了Vector的初始容量为10

第二个:创建一个空的Vector,并且指定了Vector的初始容量

第三个:创建一个空的Vector,并且指定了Vector的初始容量和扩容时的增长系数

第四个:根据其他集合来创建一个非空的Vector

第四个需要解释一下,首先是把其他集合转化为数组,然后复制粘贴到Vector里面。
(2)增加元素
增加元素有两个主要的方法,第一个是在Vector尾部追加,第二个是在指定位置插入元素。
第一个:在Vector尾部追加元素

我们再进来看一下ensureCapacityHelper(elementCount + 1)是如何实现的。

现在相当于真正扩容的方法是grow方法,别着急我们再进来看看。

在这一步我们扩容的时候首先就要排除一些异常的情况,首先就是capacityIncrement(需要增加的数量)是否大于0,如果大于0直接增加这么多。然后发现增加了上面那些还不够那就扩充为实际需要minCapacity的大小。最后发现还不够,就只能扩充到虚拟机能表示的数字最大值了。
第二个:在指定位置增加元素
这个就比较简单了。我们直接看源码就能看明白

(3)删除元素
删除元素时候同样也有两种方法,第一个根据元素值来删除,第二个根据下表来删除元素。
第一个:根据元素值来删除元素

我们发现删除元素其实是调用了removeElement()方法来删除元素的,没关系不要嫌麻烦,进入这个方法内部看一下。

到了这一步,我们又发现,执行删除操作的还不是removeElement()方法,而是removeElementAt(i),我们再进入这个方法看看。

到了这个方法我们其实可以分析一下,要删除元素要移动大量的元素,时间效率肯定是不好的。毕竟Vector是通过数组来实现的,而不是通过链表。
第二个:删除指定位置的元素
删除指定位置的元素就比较简单了,我们到指定的位置进行删除就好了,但是同样需要把后面的元素进行移位。

(3)更改元素
更改元素我们就先看一个吧。这个在大部分场景下一般不用(大部分,根据自己业务来定)。

(4)查找元素
查找元素我们给出三个,第一个查询Vector容器中是否包含某个元素,第二个查询第一次出现的指定元素的索引,第三个最后一次出现的指定元素的索引。
第一个:查询Vector容器中是否包含某个元素

我们发现,查询Vector是否包含某个元素时候,其实是调用了第二个方法,那我们直接就看第二个
第二个:查询第一次出现的指定元素的索引

第三个:查询最后一次出现的指定元素的索引

1)线程安全:
从上面的构造方法还有增删改查的操作其实我们都发现了,都有这么一个synchronized关键字,就是这个关键字为Vector容器提供了一个安全机制,保证了线程安全。
2)构造方法:
Vector实际上是通过一个数组去保存数据的。当我们构造Vecotr时;使用默认构造函数,默认容量大小是10。
3)增加元素:
当Vector容量不足以容纳全部元素时,Vector的容量会增加。若容量增加系数 大于0,则将容量的值增加“容量增加系数”;否则,将容量大小增加一倍。
4)克隆:
Vector的克隆函数,即是将全部元素克隆到一个数组中。
(5)遍历
不过到这可还没结束,还有重要的一点我们还没说,那就是遍历。其实在我之前的文章介绍ArrayList时候已经提到过了,遍历方式也就那么几种,既然Vector是基于数组实现的,那么遍历方式肯定也是随机访问最快。在这里代码演示几个:

三、Vector与其他容器的区别
源码看完了,对于Vector的实现,我相信你也基本上明白其内部实现了,下面就看看他和别的容器的区别,在文章一开始我们就提到了Vector其实基本上和ArrayList一样的,下面对比分下一下:
ArrayList是线程非安全的,这很明显,因为ArrayList中所有的方法都不是同步的,在并发下一定会出现线程安全问题。另一个方法就是Vector,它是ArrayList的线程安全版本,其实现90%和ArrayList都完全一样,区别在于:
1、Vector是线程安全的,ArrayList是线程非安全的
2、Vector可以指定增长因子,如果该增长因子指定了,那么扩容的时候会每次新的数组大小会在原数组的大小基础上加上增长因子;如果不指定增长因子,那么就给原数组大小*2,源代码是这样的:

OK,今天的文章就分享到这里,如有问题还请批评指正。
Vector线程安全,ArrayList非线程安全的更多相关文章
- JAVA中的线程安全与非线程安全
原文:http://blog.csdn.net/xiao__gui/article/details/8934832 ArrayList和Vector有什么区别?HashMap和HashTable有什么 ...
- Java线程安全和非线程安全
ArrayList是非线程安全的,Vector是线程安全的:HashMap是非线程安全的,HashTable是线程安全的:StringBuilder是非线程安全的,StringBuffer是线程安全的 ...
- 转:Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择,及详解五种运行模式。
原文来自于:http://www.ituring.com.cn/article/128439 Windows下的PHP开发环境搭建——PHP线程安全与非线程安全.Apache版本选择,及详解五种运行模 ...
- (转)PHP线程安全与非线程安全的区别:如何选择用哪一个?
PHP线程安全与非线程安全的区别:如何选择用哪一个? 很多时候,我们在做PHP环境配置的时候,很多人都是直接去乱下载PHP版本的,但是他不清楚:从2000年10月20日发布的第一个Windows版的P ...
- 为什么JAVA虚拟机分为线程共享和非线程共享?
大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) , VM Stack(虚拟 ...
- 【面试专栏】ArrayList 非线程安全案例并提供三种解决方案
1. 复现问题 import java.util.ArrayList; import java.util.List; import java.util.UUID; /** * 复现问题 * * @au ...
- java中线程安全和非线程安全的集合
线程安全 非线程安全 Collection Vector ArrayList.LinkedList HashSet.TreeSet Map HashTable HashMap.TreeMap 字符串 ...
- Java中的线程安全和非线程安全以及锁的几个知识点
1. 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用.不会出现数据不一致或者数据污染. 线程不安全就是不提供 ...
- 线程安全 Vs 非线程安全
线程安全:多线程访问时,采用了加锁机制,当一个线程读取数据时,其他线程不能访问直到该线程读取完毕.不会出现数据不一致或者脏数据. 非线程安全:不提供数据保护,可能出现其他线程访问时更改数据而该线程得到 ...
随机推荐
- Android培训准备资料之五大布局简单介绍
本篇博客主要简单的给大家介绍一下Android五大布局 (1)LinearLayout(线性布局) (2)RelativeLayout(相对布局) (3)FrameLayout(帧布局) (4)Abs ...
- GCN
REFERENCE: https://www.jianshu.com/p/ad528c40a08f https://www.zhihu.com/question/54504471 图有两个基本的特性: ...
- 关于微信小程序中遇到的各种问题汇总(持续更新)
1.关于 <input />标签容易忽略的问题: 使用<input />标签时容易忘记绑定bindblur()方法(输入框失去焦点时触发),因为用户用键盘输入时不一定会点击完成 ...
- paxos算法—今生
Paxos 定义2.1 票:即弱化形式的锁.它具备下面几个性质: 可重新发布:服务器可以重新发布新票,即使前面发布的票没有释放. 票可以过期:客户端用一张票来给服务器发送命令请求时,只有当这张票是最 ...
- (九)OpenStack---M版---双节点搭建---Swift(单节点)安装和配置
↓↓↓↓↓↓↓↓视频已上线B站↓↓↓↓↓↓↓↓ >>>>>>传送门 本次搭建仅采用Compute单节点做swift组件 1.Controller安装并配置控制节点 ...
- 面向对象程序设计(java)
201871010136-赵艳强<面向对象程序设计(java)>第二周学习总 第一部分:理论知识学习部分 一.简单的Java程序应运程序 1.标识符0标识符由字母.下划线.美元符号和数 ...
- Shell 脚本中 '$' 符号的多种用法
通常情况下,在工作中用的最多的有如下几项: $0:Shell 的命令本身 $1 到 $9:表示 Shell 的第几个参数 $? :显示最后命令的执行情况 $#:传递到脚本的参数个数 $$:脚本运行的当 ...
- python27期day06:小数据池、深浅拷贝、集合、作业题。
0.pycharm是代码块.黑窗口是小数据池.如下图: 1.驻留机制(长得像的共用一个内存地址)分小数据池缓存机制:后期开发时能明确知道.为什么不能正常使用.把经常用的东西放入规则(黑窗口)里. 数字 ...
- 洛谷P3232[HNOI2013]游走
有一个无向简单连通图,顶点从 \(1\) 编号到 \(n\),边从 \(1\) 编号到 \(m\) 小Z在该图上进行随机游走,初始时小Z在\(1\)号顶点,每一步小Z以相等的概率随机选 择当前顶点的某 ...
- A1070 Mooncake (25 分)
一.参考代码 #include<cstdio> #include<algorithm> #include<iostream> using namespace std ...