精华内容
下载资源
问答
  • 一、使用JDK1.0发布的Vector...二、使用集合类的顶层父类Collections类的synchronizedList()方法,传入参数为普通的Arraylist。 List<String> list=new ArrayList<>(); List<String> list2=Collec.

    一、使用JDK1.0发布的Vector类,因为底层方法使用了synchronized关键字,效率较低,不推荐使用。

      List<String> list=new Vector<>();

    二、使用集合类的顶层父类Collections类的synchronizedList()方法,传入参数为普通的Arraylist。

    List<String> list=new ArrayList<>();
    List<String> list2=Collections.synchronizedList(list);

    三、JUC下的CopyOnWriteArrayList方法,底层采用写入时复制(推荐使用,性能比Vector高)

    List<String> list=new CopyOnWriteArrayList<>();

     

    展开全文
  • 最近看到书上讲到并发下ArrayList是不安全的可能会导致越界,多线程冲突访问的问题,建议改进的方法是使用vector 代替 ArrayList。脑袋里浮现出几个问题: 1.Arraylist是如何导致越界的问题? 2.vector是如何保证...

    最近看到书上讲到并发下ArrayList是不安全的可能会导致越界,多线程冲突访问的问题.建议改进的方法是使用vector 代替 ArrayList。于是乎脑袋里浮现出几个问题:
    1.Arraylist是如何导致越界的问题?
    2.vector是如何保证线程的安全的?
    3.使用vector线程就一定安全吗?
    4.vector和ArrayList分别适合在什么场景下使用

    1.ArrayList如何导致越界问题?

    1.先看一下错误代码

    import java.util.ArrayList;
    public class ArrayListMultiThread {
    	static ArrayList<Integer> al = new ArrayList<Integer>(10);
    	public static class AddThread implements Runnable {
    		public void run() {
    			for (int i = 0;i <1000000; i++) {
    				al.add(i);
    			}
    		}
    		
    	}
    	public static void main(String[] args) throws InterruptedException {
    		Thread t1 = new Thread(new AddThread());
    		Thread t2 = new Thread(new AddThread());
    		t1.start();
    		t2.start();
    		t1.join();
    		t2.join();
    		System.out.println(al.size());
    	}
    
    }
    

    运行结果如下这里出现了越界在这里插入图片描述

    2.如何导致越界?

    1.先看一下需要用到的源码

    首先,ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存。
    从上面代码的报错中,我们可以看到在add方法那里出了问题,查看ArrayList中的add源码方法如下:

        /**
         * 将指定的元素追加到此列表的末尾。 
         */
        public boolean add(E e) {
       //添加元素之前,先调用ensureCapacityInternal方法
            ensureCapacityInternal(size + 1); 
            //这里看到ArrayList添加元素的实质就相当于为数组赋值
            elementData[size++] = e;//将对象e放在数组的末尾
            return true;
        }
    
    

    可以看出add方法首先调用了ensureCapacityInternal的方法,这个方法是用来得到最小的扩容量。我们再来看看ensureCapacityInternal方法:
    DEFAULTCAPACITY_EMPTY_ELEMENTDATA 是在jdk1.8中新加的。作用是根据第一个元素被添加时知道多少个元素去填充把它与EMPTY_ELEMENTDATA区分开来.

        private void ensureCapacityInternal(int minCapacity) {
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                  // 获取默认的容量和传入参数的较大值
                minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
                //源码中写道  private static final int DEFAULT_CAPACITY = 10;
            }
    
            ensureExplicitCapacity(minCapacity);
        }
    

    ensureCapacituInternal方法的最后调用了ensureExplicitCapacity方法,这个方法是用来判断是否需要扩容。我们在来看一下这个方法:

      //判断是否需要扩容
        private void ensureExplicitCapacity(int minCapacity) {
            modCount++; //表现出list结构上被修改的次数
    
            // overflow-conscious code
            if (minCapacity - elementData.length > 0)
                //调用grow方法进行扩容,调用此方法代表已经开始扩容了
                grow(minCapacity);
        }
    

    需要的源码差不多都在上面了grow方法就暂时不做描述了。

    2.ArrayList越界的逻辑

    1.假设列表大小为9,即size=9
    2.线程A开始进入add方法,这时它获取到size的值为9,调用ensureCapacityInternal方法进行容量判断。
    3.线程B此时也进入add方法,它获取到size的值也为9,也开始调用ensureCapacityInternal方法。
    4.线程A发现需求大小为10,而elementData的大小就为10,可以容纳。于是它不再扩容,返回。
    5.线程B也发现需求大小为10,也可以容纳,返回。
    6.线程A开始进行设置值操作, elementData[size++] = e 操作。此时size变为10。
    7.线程B也开始进行设置值操作,它尝试设置elementData[10] = e,而elementData没有进行过扩 容,它的下标最大为9。于是此时会报出一个数组越界的异常ArrayIndexOutOfBoundsException

    3.ArrayList导致多线程冲突访问。

    执行上面的代码我们会发现有的时候不会报错,但是结果会远小于正确值。这是由于多线程访问冲突,使的保存容器大小的变量被多线程不正常的访问,同时两个线程也同时对ArrayList中的同一个位置进行复制导致的。

    2. vector是如何保证线程安全的呢?

    上述的错误代码如果将ArrayList都换成vector,执行的结果就是正确的了。那么vector是如何保证线程的安全的呢?看源码发现vector中一些关键的方法都用synchronized修饰,这就使得每次只能有一个线程去访问,从而保证安全。

    3. 使用vector一定能保证线程的安全吗?

    很多人都会问这个问题,答案是不安全的,虽然很多方法都用synchronized修饰,保证所有对外的接口都以vector为锁,但是在单个方法的原子性方面,并不能保证符合操作的原子性。对于复合操作vector和ArrayList一样都需要进行同步处理。所以,如果是这样的话,那么用vector和ArrayList就没有区别了。因为 synchronized 的开销是巨大的,vector还会导致一些性能下降的问题。

    书上说建议使用vector代替ArrayList,看完别人的讲解发现vector还是不能乱用的,现在挺迷糊的。
    

    4.vector和ArrayList分别适合在什么场景下使用

    这个问题暂时未找到答案。o(╥﹏╥)o

    展开全文
  • Vector 类中所有的方法都是同步的,可以由两个线程安全的访问同一个Vector对象,但是一个线程访问Vector 的话就会在同步操作上耗费大量的时间。 ArrayList 不是同步的,所有在不需要保证线程安全时建议使用ArrayList...

    Vector 类中所有的方法都是同步的,可以由两个线程安全的访问同一个Vector对象,但是一个线程访问Vector 的话就会在同步操作上耗费大量的时间。

    ArrayList 不是同步的,所有在不需要保证线程安全时建议使用ArrayList 。

    ArrayList扩容机制参考

    展开全文
  • ArrayList线程安全处理

    2021-02-01 11:23:43
    //1.Collections.synchronizedList ... 使用线程安全的 CopyOnWriteArrayList 代替线程不安全的 ArrayList。 List<Object> list2=new CopyOnWriteArrayList<>(); //3.使用ThreadLocal 推荐 Threa
    //1.Collections.synchronizedList
    List<Object> list1= Collections.synchronizedList(new ArrayList<>());
    //2. 使用线程安全的 CopyOnWriteArrayList 代替线程不安全的 ArrayList。
    List<Object> list2=new CopyOnWriteArrayList<>();
    //3.使用ThreadLocal  推荐
    ThreadLocal<List<Object>> threadList=new ThreadLocal<List<Object>>(){
        @Override
        protected List<Object> initialValue(){
            return new ArrayList<>();
        }
    };
    
    展开全文
  • 1.故障现象 :ArrayList的add()方法并没有使用synchronized所以是线程不安全的,会造成java.util.ConcurrentmodificationException(并发修改异常) 2.导致原因:并发争抢修改导致 3.解决办法(以ArrayList为例,其他...
  • HashTable应用非常广泛,HashMap是新框架中用来代替HashTable类,也就是说建议使用HashMap,不要使用HashTable。 这里简单分析他们区别。 1.HashTable方法是同步,HashMap未经同步,所以在多线程场合要...
  • ArrayList 与 Vector 区别

    2020-07-20 20:43:39
    ArrayList不是同步,线程不安全,但速度较快,Vector是同步,速度慢,但已经被ArrayList代替
  • 原文链接作者:Stephen C 校对:方腾飞问:JDK 5在java.util.concurrent里引入了ConcurrentHashMap,在需要支持高并发的场景,我们可以使用它代替HashMap。...难道在多线程场景下我们只有Vector这一种线程安全的...
  • 但是为什么没有ArrayList的并发实现呢?难道在多线程场景下我们只有Vector这一种线程安全的数组实现可以选择么?为什么在java.util.concurrent 没有一个类可以代替Vector呢?答:我认为在java.util.con...
  • 原文链接作者:Stephen C译者:郑旭东校对:方腾飞 问:JDK 5在java.util.concurrent里...但是为什么没有ArrayList的并发实现呢?难道在多线程场景下我们只有Vector这一种线程安全的数组实现可以选择么?为什么在ja...
  • Vector和ArrayList异同

    2018-05-23 14:15:51
    值得注意的是Vector与ArrayList唯一的区别是,Vector是线程安全的,即它的大部分方法都包含有关键字synchronized,因此,若对于单一线程的应用来说,最好使用ArrayList代替Vector,因为这样效率会快很多(类似的情况...
  • Vector和ArrayList异同 ?

    2018-05-23 19:39:44
    值得注意的是Vector与ArrayList唯一的区别是,Vector是线程安全的,即它的大部分方法都包含有关键字synchronized,因此,若对于单一线程的应用来说,最好使用ArrayList代替Vector,因为这样效率会快很多(类似的情况...
  • ArrayList类图总结 ArrayList的默认容量是10/** * Default initial capacity. ...不同于Vector,ArrayList是线程不安全的,可以使用并发容器CopyOnWirteArrayList代替 ArrayList底层是使用对象数组实现的,继承了Ab
  • 我们已经知道多线程下会有各种不安全的问题,都知道并发的基本解决方案,这里对出现错误的情况进行一个实际模拟,以此能够联想到具体的生产环境中。 一、List 的不安全 1.1 问题 看一段代码: public static void ...
  • 原文链接作者:Stephen C译者:郑旭东校对:方腾飞问:JDK ...但是为什么没有ArrayList的并发实现呢?难道在多线程场景下我们只有Vector这一种线程安全的数组实现可以选择么?为什么在java.util.concurrent 没有一个...
  • 原文链接作者:Stephen C译者:郑旭东校对:方腾飞问:JDK ...但是为什么没有ArrayList的并发实现呢?难道在多线程场景下我们只有Vector这一种线程安全的数组实现可以选择么?为什么在java.util.concurrent 没有一个...
  • 集合线程安全问题

    2020-09-05 18:57:57
    1.如何解决ArrayList线程不安全问题呢? 1.用Vector代替ArrayList 2.用Collections.synchronized(new ArrayList<>()) List<Object> arrayList = Collections.synchronizedList(new ArrayList<>...
  • list的线程安全的类型

    千次阅读 2016-09-17 23:58:22
    list安全可以用Vector代替,或者用Collections.synchronizedList(new ArrayList())来定义一个线程安全的list。
  • ArrayList是线程不安全的,用Vector、Stack代替, 但是,Vector不一定就是安全的,若使用forEach或者Iterator遍历集合的时候做更新操作,会引发异常,而使用for循环则不会; package com.concurrent.example; ...
  • 如果不需要线程安全的实现,建议使用ArrayList代替Vector * 几乎所有的方法都是synchronized方法修饰的。 */ package java.util; import java.io.IOException; import java.io.ObjectInput...
  • 在《Practical Java》一书中Peter Haggar建议使用一个简单数组(Array)来代替Vector或ArrayList。尤其是对于执行效率要求高程序更应如此。因为[b]使用数组(Array)避免了同步[/b]、额外方法调用和不必要重新...
  • 同步容器类包括Vector和Hashtable,二者是早期JDK的一部分,这两个容器的实现和早期的ArrayList和HashMap代码实现基本一样,此外还包括在JDK1.2中添加的一些功能相似的类,这些同步的封装器类是由Collections....
  • ArrayList像,都是由数组实现内部存储结构, 已经被ArrayList代替 Vector线程安全,效率较低,ArrayList线程不安全,效率较高,重效率轻安全 扩容:每次扩容原容量2倍,没有ArrayList节省空间 LinkedList 就是在存储数据...

空空如也

空空如也

1 2 3 4 5
收藏数 88
精华内容 35
关键字:

安全的arraylist的代替