http://baijiahao.baidu.com/s?id=1638844080997170869&wfr=spider&for=pc

Vector线程安全,ArrayList非线程安全

java的架构师技术栈

发布时间:07-1217:25科技达人,优质原创作者

这篇文章开始介绍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非线程安全的更多相关文章

  1. JAVA中的线程安全与非线程安全

    原文:http://blog.csdn.net/xiao__gui/article/details/8934832 ArrayList和Vector有什么区别?HashMap和HashTable有什么 ...

  2. Java线程安全和非线程安全

    ArrayList是非线程安全的,Vector是线程安全的:HashMap是非线程安全的,HashTable是线程安全的:StringBuilder是非线程安全的,StringBuffer是线程安全的 ...

  3. 转:Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择,及详解五种运行模式。

    原文来自于:http://www.ituring.com.cn/article/128439 Windows下的PHP开发环境搭建——PHP线程安全与非线程安全.Apache版本选择,及详解五种运行模 ...

  4. (转)PHP线程安全与非线程安全的区别:如何选择用哪一个?

    PHP线程安全与非线程安全的区别:如何选择用哪一个? 很多时候,我们在做PHP环境配置的时候,很多人都是直接去乱下载PHP版本的,但是他不清楚:从2000年10月20日发布的第一个Windows版的P ...

  5. 为什么JAVA虚拟机分为线程共享和非线程共享?

    大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) , VM Stack(虚拟 ...

  6. 【面试专栏】ArrayList 非线程安全案例并提供三种解决方案

    1. 复现问题 import java.util.ArrayList; import java.util.List; import java.util.UUID; /** * 复现问题 * * @au ...

  7. java中线程安全和非线程安全的集合

    线程安全 非线程安全 Collection Vector ArrayList.LinkedList HashSet.TreeSet Map HashTable HashMap.TreeMap 字符串 ...

  8. Java中的线程安全和非线程安全以及锁的几个知识点

    1. 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用.不会出现数据不一致或者数据污染. 线程不安全就是不提供 ...

  9. 线程安全 Vs 非线程安全

    线程安全:多线程访问时,采用了加锁机制,当一个线程读取数据时,其他线程不能访问直到该线程读取完毕.不会出现数据不一致或者脏数据. 非线程安全:不提供数据保护,可能出现其他线程访问时更改数据而该线程得到 ...

随机推荐

  1. JavaWeb之文件上传和下载

    在如今的互联网时代,人们越来越喜欢将自己的数据存放到互联网上,于是便诞生了很多类型的软件,比如360网盘,百度网盘,云盘之类的.所以说,文件上传和下载的功能是现在非常主流的一个功能,应用十分广泛. 那 ...

  2. liteos互斥锁(七)

    1. 概述 1.1 基本概念 互斥锁又称互斥型信号量,是一种特殊的二值性信号量,用于实现对共享资源的独占式处理. 任意时刻互斥锁的状态只有两种,开锁或闭锁.当有任务持有时,互斥锁处于闭锁状态,这个任务 ...

  3. NVIDIA-SMI参数解析

    第一栏的Fan:N/A是风扇转速,从0到100%之间变动,这个速度是计算机期望的风扇转速,实际情况下如果风扇堵转,可能打不到显示的转速.有的设备不会返回转速,因为它不依赖风扇冷却而是通过其他外设保持低 ...

  4. ansible 模块 roles

    setup 作用,用来查看用看内部的详细信息 ansible_all_ipv4_addresses # ipv4的所有地址 ansible_all_ipv6_addresses # ipv6的所有地址 ...

  5. 201871010126 王亚涛 《面向对象程序设计(Java)》第八周实验总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

  6. jmeter引用jar包的3种方式

    示例 实现对登录密码进行MD5加密 pom文件依赖 <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec --& ...

  7. java.util.Base64

    Base64 简单使用 java.util.Base64 package com.mozq.sb.jwt01.config; import java.nio.charset.Charset; impo ...

  8. AWS云教育账号创建以及搭建数据库

    注册过程繁琐,本文强调关键几点 首先拿到aws的二维码,进入之后填写相关个人信息,用学校邮箱注册,用学校邮箱注册!! 之后审核会有大约10分钟的过程,之后会收到确认邮件 点进去之后就可以设置自己的密码 ...

  9. 关于几类STL容器swap的复杂度问题

    \(swap\)的方式有 \(S1.swap(S2)\) 或 \(swap(S1,S2)\) \(vector,map,set,deque \ \ \ \ swap\)复杂度:\(O(1)\) \(p ...

  10. Intellij IDEA使用一 创建javaweb项目并配置tomcat

    一.新建Java web项目 参考:https://blog.csdn.net/chengtengfei352/article/details/79211619 1.点击创建新项目 2. 3.crea ...