Bootstrap

java 集合哪些是安全的哪些不安全的?

首先给出结论,ArrayList,LinkedList,HashMap,StringBuilder是不安全的。vector,HashTable,StringBuffer是线程安全的。下面用代码来看看。


Java API中所用的集合类,都是实现了Collection接口,他的一个类继承结构如下: Collection<–List<–Vector Collection<–List<–ArrayList Collection<–List<–LinkedList Collection<–Set<–HashSet Collection<–Set<–HashSet<–LinkedHashSet Collection<–Set<–SortedSet<–TreeSet Vector : 基于Array的List,其实就是封装了Array所不具备的一些功能方便我们使用,它不可能走入Array的限制。性能也就不可能超越Array。所以,在可能的情况下,我们要多运用Array。另外很重要的一点就是Vector“sychronized”的,这个也是Vector和ArrayList的唯一的区别。 ArrayList:同Vector一样是一个基于Array上的链表,但是不同的是ArrayList不是同步的。所以在性能上要比Vector优越一些,但是当运行到多线程环境中时,可需要自己在管理线程的同步问题。 LinkedList:LinkedList不同于前面两种List,它不是基于Array的,所以不受Array性能的限制。它每一个节点(Node)都包含两方面的内容:1.节点本身的数据(data);2.下一个节点的信息(nextNode)。所以当对LinkedList做添加,删除动作的时候就不用像基于Array的List一样,必须进行大量的数据移动。只要更改nextNode的相关信息就可以实现了。这就是LinkedList的优势。 List总结: 1. 所有的List中只能容纳单个不同类型的对象组成的表,而不是Key-Value键值对。例如:[ tom,1,c ]; 2. 所有的List中可以有相同的元素,例如Vector中可以有 [ tom,koo,too,koo ]; 3. 所有的List中可以有null元素,例如[ tom,null,1 ]; 4. 基于Array的List(Vector,ArrayList)适合查询,而LinkedList(链表)适合添加,删除操作。 HashSet:虽然Set同List都实现了Collection接口,但是他们的实现方式却大不一样。List基本上都是以Array为基础。但是Set则是在HashMap的基础上来实现的,这个就是Set和List的根本区别。HashSet的存储方式是把HashMap中的Key作为Set的对应存储项。
  1. ArrayList测试
package testThread;

import java.util.ArrayList;
import java.util.List;

class Ticket implements  Runnable {
    private static int t=0;
    List<Integer> data = new ArrayList<>();
    boolean flag=true;  
    public void run() { 
        while (flag) {
            if (t<100) {
                  data.add(t);
                  t++;
                  //System.out.println(t);
                    }else {                                             
                        flag=false;
                        System.out.println("数据宽度"+data.size());                                 
                        for (int i = 0; i < data.size(); i++) {
                            System.out.println(data.get(i));
                        }
                    }           
        }

    }   
}
public class thread1 {
     public static  void main(String[] args)
     {
        Ticket t=new Ticket();
        Thread t1=new Thread(t);   
        Thread t2=new Thread(t);
        Thread t3=new Thread(t);
        t1.start();
        t2.start();     
        t3.start();

     }
}


ArrayList测试结果
这里写图片描述
2.LinkedList

package te;
import java.util.LinkedList;
import java.util.List;

class Ticket implements  Runnable {
    private static int t=0;
    List<Integer> data = new LinkedList<Integer>();
    boolean flag=true;  
    public void run() { 
        while (flag) {
            if (t<100) {
                  data.add(t);
                  t++;
                  //System.out.println(t);
                    }else {                                             
                        flag=false;
                        System.out.println("数据宽度"+data.size());                                 
                        for (int i = 0; i < data.size(); i++) {
                            System.out.println(data.get(i));
                        }
                    }           
        }

    }   
}
public class Thread7 {
     public static  void main(String[] args)
     {
        Ticket t=new Ticket();
        Thread t1=new Thread(t);   
        Thread t2=new Thread(t);
        Thread t3=new Thread(t);
        t1.start();
        t2.start();     
        t3.start();

     }
}


LinkedList结果
这里写图片描述

3.HashMap

package te;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

class Ticket implements  Runnable {
    private static int t=0;
    Map data = new HashMap<Integer,Integer>();
    boolean flag=true;  
    public void run() { 
        while (flag) {
            if (t<100) {
                  data.put(t,t);
                  t++;
                  //System.out.println(t);
                    }else {                                             
                        flag=false;                                                         
                        Collection da=data.values();
                        Iterator<Integer> it=da.iterator();
                        while (it.hasNext()) {
                            Integer integer = (Integer) it.next();
                            System.err.println(integer);

                        }
                    }           
        }

    }   
}
public class Thread7 {
     public static  void main(String[] args)
     {
        Ticket t=new Ticket();
        Thread t1=new Thread(t);   
        Thread t2=new Thread(t);
        Thread t3=new Thread(t);
        t1.start();
        t2.start();     
        t3.start();

     }
}


HashMap测试
这里写图片描述
4.vector

package te;
import java.util.Vector;

class Ticket implements  Runnable {
    private static int t=0;
    Vector<Integer> vector=new Vector<Integer>();
    boolean flag=true;  
    public void run() { 
        while (flag) {
            if (t<100) {
                  vector.add(t);
                  t++;            
                    }else {                                             
                        flag=false;                                                         
                        for(int i=0;i<vector.size();i++)
                        {
                            System.out.println(vector.get(i));
                        }
                    }           
        }

    }   
}
public class Thread7 {
     public static  void main(String[] args)
     {
        Ticket t=new Ticket();
        Thread t1=new Thread(t);   
        Thread t2=new Thread(t);
        Thread t3=new Thread(t);
        t1.start();
        t2.start();     
        t3.start();

     }
}


vector线程是安全的
5.stringbuilder和stringbuffer

package te;

class Ticket implements  Runnable {
    private static int t=0;

     StringBuffer sb = new StringBuffer();  
     StringBuilder sc=new StringBuilder();
    boolean flag=true;  
     public void run() {    
        while (flag) {
            if (t<100) {
                  sb.append(t+"a ");
                  sc.append(t+"a ");
                  t++;            
                    }else {                                             
                        flag=false;                                                         
                        System.out.println("stringbuffer"+sb);
                        System.out.println("stringbuilder"+sc);
                    }           
        }

    }   
}
public class Thread7 {
     public static  void main(String[] args)
     {
        Ticket t=new Ticket();
        Thread t1=new Thread(t);   
        Thread t2=new Thread(t);
        Thread t3=new Thread(t);
        t1.start();
        t2.start();     
        t3.start();

     }
}


结果测试 stringbuilder是不安全的
这里写图片描述

6.分析总结
凡是线程不安全的,我们可以来看源码来分析 ,这是arraylist的源码,我们很容易发现这是由于没有synchronized关键字。

 public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
      
      

再来看看vector,有synchronized关键字。

 public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }

;