欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java concurrency集合之CopyOnWriteArraySet_動力節(jié)點(diǎn)Java學(xué)院整理

 更新時間:2017年06月13日 10:06:20   作者:skywang12345  
CopyOnWriteArraySet基于CopyOnWriteArrayList實(shí)現(xiàn),其唯一的不同是在add時調(diào)用的是CopyOnWriteArrayList的addIfAbsent(若沒有則增加)方法

CopyOnWriteArraySet介紹

它是線程安全的無序的集合,可以將它理解成線程安全的HashSet。有意思的是,CopyOnWriteArraySet和HashSet雖然都繼承于共同的父類AbstractSet;但是,HashSet是通過“散列表(HashMap)”實(shí)現(xiàn)的,而CopyOnWriteArraySet則是通過“動態(tài)數(shù)組(CopyOnWriteArrayList)”實(shí)現(xiàn)的,并不是散列表。

和CopyOnWriteArrayList類似,CopyOnWriteArraySet具有以下特性:

1. 它最適合于具有以下特征的應(yīng)用程序:Set 大小通常保持很小,只讀操作遠(yuǎn)多于可變操作,需要在遍歷期間防止線程間的沖突。

2. 它是線程安全的。

3. 因?yàn)橥ǔP枰獜?fù)制整個基礎(chǔ)數(shù)組,所以可變操作(add()、set() 和 remove() 等等)的開銷很大。

4. 迭代器支持hasNext(), next()等不可變操作,但不支持可變 remove()等 操作。

5. 使用迭代器進(jìn)行遍歷的速度很快,并且不會與其他線程發(fā)生沖突。在構(gòu)造迭代器時,迭代器依賴于不變的數(shù)組快照。

CopyOnWriteArraySet原理和數(shù)據(jù)結(jié)構(gòu)

CopyOnWriteArraySet的數(shù)據(jù)結(jié)構(gòu),如下圖所示:

說明:

  1. CopyOnWriteArraySet繼承于AbstractSet,這就意味著它是一個集合。

  2. CopyOnWriteArraySet包含CopyOnWriteArrayList對象,它是通過CopyOnWriteArrayList實(shí)現(xiàn)的。而CopyOnWriteArrayList本質(zhì)是個動態(tài)數(shù)組隊(duì)列,

所以CopyOnWriteArraySet相當(dāng)于通過通過動態(tài)數(shù)組實(shí)現(xiàn)的“集合”! CopyOnWriteArrayList中允許有重復(fù)的元素;但是,CopyOnWriteArraySet是一個集合,所以它不能有重復(fù)集合。因此,CopyOnWriteArrayList額外提供了addIfAbsent()和addAllAbsent()這兩個添加元素的API,通過這些API來添加元素時,只有當(dāng)元素不存在時才執(zhí)行添加操作!

至于CopyOnWriteArraySet的“線程安全”機(jī)制,和CopyOnWriteArrayList一樣,是通過volatile和互斥鎖來實(shí)現(xiàn)的。這個在前一章節(jié)介紹CopyOnWriteArrayList時數(shù)據(jù)結(jié)構(gòu)時,已經(jīng)進(jìn)行了說明,這里就不再重復(fù)敘述了。

CopyOnWriteArraySet函數(shù)列表

// 創(chuàng)建一個空 set。
CopyOnWriteArraySet()
// 創(chuàng)建一個包含指定 collection 所有元素的 set。
CopyOnWriteArraySet(Collection<? extends E> c)

// 如果指定元素并不存在于此 set 中,則添加它。
boolean add(E e)
// 如果此 set 中沒有指定 collection 中的所有元素,則將它們都添加到此 set 中。
boolean addAll(Collection<? extends E> c)
// 移除此 set 中的所有元素。
void clear()
// 如果此 set 包含指定元素,則返回 true。
boolean contains(Object o)
// 如果此 set 包含指定 collection 的所有元素,則返回 true。
boolean containsAll(Collection<?> c)
// 比較指定對象與此 set 的相等性。
boolean equals(Object o)
// 如果此 set 不包含任何元素,則返回 true。
boolean isEmpty()
// 返回按照元素添加順序在此 set 中包含的元素上進(jìn)行迭代的迭代器。
Iterator<E> iterator()
// 如果指定元素存在于此 set 中,則將其移除。
boolean remove(Object o)
// 移除此 set 中包含在指定 collection 中的所有元素。
boolean removeAll(Collection<?> c)
// 僅保留此 set 中那些包含在指定 collection 中的元素。
boolean retainAll(Collection<?> c)
// 返回此 set 中的元素?cái)?shù)目。
int size()
// 返回一個包含此 set 所有元素的數(shù)組。
Object[] toArray()
// 返回一個包含此 set 所有元素的數(shù)組;返回?cái)?shù)組的運(yùn)行時類型是指定數(shù)組的類型。
<T> T[] toArray(T[] a)

CopyOnWriteArraySet是通過CopyOnWriteArrayList實(shí)現(xiàn)的,它的API基本上都是通過調(diào)用CopyOnWriteArrayList的API來實(shí)現(xiàn)的。相信對CopyOnWriteArrayList了解的話,對CopyOnWriteArraySet的了解是水到渠成的事;所以,這里就不再對CopyOnWriteArraySet的代碼進(jìn)行詳細(xì)的解析了。 

CopyOnWriteArraySet示例

下面,我們通過一個例子去對比HashSet和CopyOnWriteArraySet。

import java.util.*;
import java.util.concurrent.*;

/*
 *  CopyOnWriteArraySet是“線程安全”的集合,而HashSet是非線程安全的。
 *
 *  下面是“多個線程同時操作并且遍歷集合set”的示例
 *  (01) 當(dāng)set是CopyOnWriteArraySet對象時,程序能正常運(yùn)行。
 *  (02) 當(dāng)set是HashSet對象時,程序會產(chǎn)生ConcurrentModificationException異常。
 *
 * 
 */
public class CopyOnWriteArraySetTest1 {

  // TODO: set是HashSet對象時,程序會出錯。
  //private static Set<String> set = new HashSet<String>();
  private static Set<String> set = new CopyOnWriteArraySet<String>();
  public static void main(String[] args) {
  
    // 同時啟動兩個線程對set進(jìn)行操作!
    new MyThread("ta").start();
    new MyThread("tb").start();
  }

  private static void printAll() {
    String value = null;
    Iterator iter = set.iterator();
    while(iter.hasNext()) {
      value = (String)iter.next();
      System.out.print(value+", ");
    }
    System.out.println();
  }

  private static class MyThread extends Thread {
    MyThread(String name) {
      super(name);
    }
    @Override
    public void run() {
        int i = 0;
      while (i++ < 10) {
        // “線程名” + "-" + "序號"
        String val = Thread.currentThread().getName() + "-" + (i%6);
        set.add(val);
        // 通過“Iterator”遍歷set。
        printAll();
      }
    }
  }
}

(某一次)運(yùn)行結(jié)果:

ta-1, tb-1, ta-1, 
tb-1, ta-1, 
tb-1, ta-1, ta-2, 
tb-1, ta-1, ta-2, tb-1, tb-2, 
ta-2, ta-1, tb-2, tb-1, ta-3, 
ta-2, ta-1, tb-2, tb-1, ta-3, ta-2, tb-3, 
tb-2, ta-1, ta-3, tb-1, tb-3, ta-2, ta-4, 
tb-2, ta-1, ta-3, tb-1, tb-3, ta-2, ta-4, tb-2, tb-4, 
ta-3, ta-1, tb-3, tb-1, ta-4, ta-2, tb-4, tb-2, ta-5, 
ta-3, ta-1, tb-3, tb-1, ta-4, ta-2, tb-4, tb-2, ta-5, ta-3, tb-5, 
tb-3, ta-1, ta-4, tb-1, tb-4, ta-2, ta-5, tb-2, tb-5, ta-3, ta-0, 
tb-3, ta-1, ta-4, tb-1, tb-4, ta-2, ta-5, tb-2, tb-5, ta-3, ta-0, tb-3, tb-0, 
ta-4, ta-1, tb-4, tb-1, ta-5, ta-2, tb-5, tb-2, ta-0, ta-3, tb-0, 
tb-3, ta-1, ta-4, tb-1, tb-4, ta-2, ta-5, tb-5, ta-0, tb-0, 
ta-1, tb-2, tb-1, ta-3, ta-2, tb-3, tb-2, ta-4, ta-3, tb-4, tb-3, ta-5, ta-4, tb-5, tb-4, ta-0, ta-5, tb-0, 
tb-5, ta-1, ta-0, tb-1, tb-0, 
ta-2, ta-1, tb-2, tb-1, ta-3, ta-2, tb-3, tb-2, ta-4, ta-3, tb-4, tb-3, ta-5, tb-5, ta-0, tb-0, 
ta-4, ta-1, tb-4, tb-1, ta-5, ta-2, tb-5, tb-2, ta-0, ta-3, tb-0, 
tb-3, ta-1, ta-4, tb-1, tb-4, ta-2, ta-5, tb-2, tb-5, ta-3, ta-0, tb-3, tb-0, 
ta-4, tb-4, ta-5, tb-5, ta-0, tb-0, 

結(jié)果說明:

由于set是集合對象,因此它不會包含重復(fù)的元素。

如果將源碼中的set改成HashSet對象時,程序會產(chǎn)生ConcurrentModificationException異常。

相關(guān)文章

最新評論