zoukankan      html  css  js  c++  java
  • java中线程安全和非线程安全的集合

    线程安全

    非线程安全

    Collection

    Vector

    ArrayList、LinkedList

     

    HashSet、TreeSet

    Map

    HashTable

    HashMap、TreeMap

    字符串

    StringBuffer

    StringBuilder

    一、ArrayList和vector区别
    Vector和ArrayList间唯一的区别就是Vector每个方法都自带同步机制。
    例:比如我要往集合里面加一个元素,又要保证多个线程不会同时调用同一个对象的add()方法,ArrayList里面就要这样写:

    ArrayList<String> list = new ArrayList<>();
    synchronized (list) {
        list.add("233");
    }

    而Vector里面只要这样写就行了:

    Vector<String> list = new Vector<>();
    list.add("233");

    因为ArrayList的add方法是这样定义的:

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

    而Vector的add方法是这样定义的:

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

    二、HashTable、HashMap、HashSet:
    HashTable和HashMap采用的存储机制是一样的,不同的是:
    1、HashMap:
    a. 非线程安全;
    b. 采用数组方式存储key-value构成的Entry对象,key允许为null,无容量限制;
    c. 遍历使用的是Iterator迭代器;

    2、HashTable:
    a. 线程安全; (对方法加上synchronized
    b. 无论是key还是value都不允许有null值的存在;在HashTable中调用Put方法时,如果key为null,直接抛出NullPointerException异常;
    c. 遍历使用的是Enumeration列举;

    3、HashSet:
    a. 非线程安全
    b. 底层通过HashMap实现,无容量限制;
    c. 不保证数据的有序;

    在HashSet中,元素都存到HashMap键值对的Key上面,而Value是统一的值private static final Object PRESENT = new Object();,(定义一个虚拟的Object对象作为HashMap的value,将此对象定义为static final。)
    HashSet的add(E e)底层实现调用hashmap的put(E e),将该元素作为key放入HashMap。
    由于HashMap的put()方法添加key-value对时,当新放入HashMap的Entry中key与集合中原有Entry的key相同(hashCode()返回值相等,通过equals比较也返回true), 新添加的Entry的value会将覆盖原来Entry的value,但key不会有任何改变, 因此如果向HashSet中添加一个已经存在的元素时,新添加的集合元素将不会被放入HashMap中, 原来的元素也不会有任何改变,这也就满足了Set中元素不重复的特性。

    HashSet参考:http://zhangshixi.iteye.com/blog/673143

    三、TreeSet、TreeMap:
    TreeSet和TreeMap都是完全基于Map来实现的,并且都不支持get(index)来获取指定位置的元素,需要遍历来获取。另外,TreeSet还提供了一些排序方面的支持,例如传入Comparator实现、descendingSet以及descendingIterator等。
    1、TreeSet:
    a. 非线程安全
    b. 底层基于TreeMap实现,支持排序;

    2、TreeMap:
    a. 非线程安全;
    b. 典型的基于红黑树的Map实现,因此它要求一定要有key比较的方法,要么传入Comparator比较器实现,要么key对象实现Comparator接口;

    与hashmap相比,treemap内部的元素都是排序的,当需要查找某些元素以及顺序输出元素的时候占优势。因此,TreeMap是一个内部元素排序版的HashMap

    四、StringBuffer和StringBulider:
    StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串。
    它们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,不像String一样创建一些对象进行操作,所以速度就快了;
    1、在执行速度方面的比较:StringBuilder > StringBuffer ;
    2、StringBuilder:非线程安全;
    3、StringBuffer:线程安全; (对方法加上synchronized
     
    对于String、StringBuffer和StringBulider三者使用的总结:
    1.如果要操作少量的数据:String
    2.单线程操作字符串缓冲区下操作大量数据:StringBuilder
    3.多线程操作字符串缓冲区下操作大量数据:StringBuffer


    非线程安全!=不安全
    虽然ArrayList是线程不安全的,但不代表在多线程下不能使用ArrayList,只能使用Vector。
    非线程安全并不是多线程环境下就不能使用。线程安全问题在于:多线程操作同一个对象。注意是同一个对象。比如最上面那个模拟,就是在主线程中new的一个ArrayList然后多个线程操作同一个ArrayList对象。
    如果是每个线程中new一个ArrayList,而这个ArrayList只在这一个线程中使用,那么肯定是没问题的。

    参考:
    https://blog.csdn.net/u011389474/article/details/54602812
    https://www.zhihu.com/question/49855966

  • 相关阅读:
    UML画图
    UML笔记
    电脑启动顺序
    评教有感
    部署图
    活动图
    给八期授课之主板电池的思考
    给八期授课之人员分配的思考
    构件图
    cocos2dx获得机器语言
  • 原文地址:https://www.cnblogs.com/zeroingToOne/p/9525240.html
Copyright © 2011-2022 走看看