The difference between Vector and ArrayList and Vector is not absolutely thread-safe

Reprinted from: https://www.cnblogs.com/zhangzongle/p/5432212.html

Difference between Vector and ArrayList in Java

First of all, these two classes implement the List interface, and the List interface has a total of three implementation classes, namely ArrayList, Vector and LinkedList. List is used to store multiple elements, can maintain the order of elements, and allow repetition of elements. The relevant differences between the three concrete implementation classes are as follows:

  1. ArrayList is the most commonly used List implementation class. Internally, it is implemented through an array, which allows fast random access to elements. The disadvantage of the array is that there can be no space between each element. When the size of the array is not sufficient, the storage capacity needs to be increased, and the data of the existing array must be copied to the new storage space. When inserting or deleting elements from the middle of the ArrayList, the array needs to be copied, moved, and the cost is relatively high. Therefore, it is suitable for random lookups and traversals, not for insertions and deletions.
  2. Like ArrayList, Vector is also implemented through arrays. The difference is that it supports thread synchronization, that is, only one thread can write Vector at a certain time, avoiding the inconsistency caused by multiple threads writing at the same time, but it requires a high cost to achieve synchronization. , so accessing it is slower than accessing an ArrayList.
  3. LinkedList uses a linked list structure to store data, which is very suitable for dynamic insertion and deletion of data, and the speed of random access and traversal is relatively slow. In addition, it also provides methods that are not defined in the List interface, which are specially used to operate the header and footer elements, which can be used as stacks, queues and bidirectional queues.
  4. Vector is thread (Thread) synchronized (Synchronized), so it is also thread safe, and Arraylist is thread asynchronous (ASynchronized), it is not safe. If the thread safety factor is not considered, it is generally more efficient to use Arraylist.
  5. If the number of elements in the collection is greater than the length of the current collection array, the vector growth rate is 100% of the current array length, while the arraylist growth rate is
    50% of the current array length. For example, if a large amount of data is used in the collection , there are certain advantages to using vector.

  6. If you look for data at a specified location, the time used by vector and arraylist is the same, both are 0 (1), and both vector and arraylist can be used at this time. And
    if the time it takes to move the data of a specified location is 0(ni)n is the total length, at this time, you should consider using Linkedlist, because it
    takes 0(1) to move the data of a specified location, and the query The time spent on data at a specified location is 0(i).
    ArrayList and Vector use arrays to store data. The number of elements in this array is larger than the actual data stored in order to add and insert elements.
    Direct serial number index elements are allowed, but the inserted data needs to be designed to memory operations such as array element movement, so the index data is inserted quickly. Data is slow.
    Vector uses the synchronized method (thread safety), so its performance is worse than ArrayList
    . LinkedList uses a doubly linked list for storage. Indexing data by serial number needs to be traversed forward or backward, but when inserting data, only this item needs to be recorded. The preceding and following items can be used, so inserting several times is faster!

  7. In general terms: LinkedList: add, delete and modify fast
                  ArrayList: fast query (there is an index)

About Vector, it's really a bit of a pit. Ali, I tried to interview, the interviewer asked me, Vector, you said that it is thread-safe, how does it achieve safety?

I replied: Many of his methods use the synchronized keyword to achieve synchronization

He asked me again, is there any other way for Vector to achieve synchronization? I thought at the time, there is nothing more complicated in the source code, just rely on this keyword to do it.

难不成是我没看到,眼瞎了?有知道的告诉我下啊,(那个modcount不是,就不用跟我说了)

Vector还真不算是线程安全,https://blog.csdn.net/zlp1992/article/details/50433778这里就很详细的展示了什么叫

实力坑爹:

先看段代码:

    private static Vector<Integer> vector=new Vector();

    public static void main(String[] args) {
        while(true){
            for(int i=0;i<10;i++){
                vector.add(i); //往vector中添加元素
            }
            Thread removeThread=new Thread(new Runnable() {         
                @Override
                public void run() {
                    //获取vector的大小
                    for(int i=0;i<vector.size();i++){
                        //当前线程让出CPU,使例子中的错误更快出现
                        Thread.yield();
                        //移除第i个数据
                        vector.remove(i);
                    }
                }
            });
            Thread printThread=new Thread(new Runnable() {          
                @Override
                public void run() {
                    //获取vector的大小
                    for(int i=0;i<vector.size();i++){
                        //当前线程让出CPU,使例子中的错误更快出现
                        Thread.yield();
                        //获取第i个数据并打印
                        System.out.println(vector.get(i));
                    }
                }
            });         
            removeThread.start();
            printThread.start();
            //避免同时产生过多线程
            while(Thread.activeCount()>20);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

运行之后,会有如下异常:

4
6
6
1
8
3
5
Exception in thread "Thread-285" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 11
    at java.util.Vector.get(Unknown Source)
    at VectorTest$2.run(VectorTest.java:31)
    at java.lang.Thread.run(Unknown Source)
7
9
0
6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

这表明上述代码在使用Vector的时候线程并不是安全的,使用get访问Vector时出现了越界。这是为什么呢? 
Vector类中对get以及remove,size方法都加了synchronized关键字来保证同步,也就说当一个线程调用了这些方法时,其他线程不能再同时调用这些方法。换言之,不能出现两个及两个以上的线程在同时调用这些同步方法。 
那么为什么例子中会出现问题呢?这是因为 例子中有些线程连续调用了两个或两个以上的同步方法。 
例子中 removeThread线程先调用了vector.size()方法获得vector的大小,接着调用vector.remove(i)移除第i个元素;而printThread线程也先调用vector.size()方法获得vector的大小,接着调用vector.get()获得第i个元素。

假设此时vector大小为5,此时printThread线程执行到 i=4 ,进入for循环但在 System.out.println(vector.get(i));之前 printThread线程的CPU时间片已到,线程printThread转入就绪状态; 
此时removeThread线程获得CPU开始执行,把vector的5个元素全删除了,这是removeThreadCPU时间片已到; 
接着printThread获得CPU进行执行,由于之前printThread中的i==4,于是调用vector.get(4)获取元素,此时由于vector中的元素已被removeThread线程全部删除,因此报错。

总的来说,vector保证了其同步方法不能被两个及两个以上线程同时访问,但是我们自己的操作会使得即使使用了Vector线程也不安全,如果不大清楚,最好自己加上 synchronized进行同步吧。

以上是copy人家的实验,充分展示了Vector不靠谱的一点,所以即便是应用java封装好的所谓的线程安全的类,也要自己好好

思考一下,小心被坑。。。。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324891898&siteId=291194637