深いJava集合学習シリーズ:深いCopyOnWriteArraySet

15948 ワード

http://www.cnblogs.com/skywang12345/p/3498497.html?utm_source=tuicool
概要
本章はJUCシリーズにおけるCopyOnWriteArraySet編です.次に、CopyOnWriteArraySetについて基本的に説明してから、その原理を説明し、コードで分析し、最後に例を通してCopyOnWriteArraySetをさらに理解します.内容は以下のとおりです:CopyOnWriteArraySet紹介CopyOnWriteArraySet原理とデータ構造CopyOnWriteArraySet関数リストCopyOnWriteArraySetソースコード(JDK 1.7.0_40バージョン)CopyOnWriteArraySet例
転載は出典を明記してください.http://www.cnblogs.com/skywang12345/p/3498497.html
 
CopyOnWriteArraySet紹介
スレッドセキュリティの無秩序な集合であり,スレッドセキュリティのHashSetとして理解できる.興味深いことに、CopyOnWriteArraySetとHashSetは共通の親AbstractSetに継承されていますが、しかし、HashSetは「ハッシュ・リスト(HashMap)」によって実現され、CopyOnWriteArraySetは「動的配列(CopyOnWriteArrayList)」によって実現され、ハッシュ・リストではない.CopyOnWriteArrayListと同様に、CopyOnWriteArraySetは以下の特性を有する.Setサイズは通常小さく維持され、読み取り専用操作は可変操作よりはるかに多く、遍歴中にスレッド間の競合を防止する必要があるという特徴を持つアプリケーションに最適です.2.スレッドが安全です.3.通常、ベース配列全体をコピーする必要があるため、可変操作(add()、set()、remove()など)のオーバーヘッドが大きい.4.反復器はhasNext()、next()などの可変操作をサポートするが、可変remove()などの操作はサポートしない.5.反復器を使用して遍歴する速度が速く、他のスレッドと競合しません.反復器を構築するとき、反復器は不変の配列スナップショットに依存します.
提案:CopyOnWriteArraySetを学習する前に、「Javaコレクション16のHashSet詳細(ソースコード解析)と使用例」でHashSetについて説明します.
 
CopyOnWriteArraySetの原理とデータ構造
CopyOnWriteArraySetのデータ構造を下図に示します.

説明:1.CopyOnWriteArraySetはAbstractSetに継承され、これは集合であることを意味します.  2. CopyOnWriteArraySetには、CopyOnWriteArrayListによって実現されるCopyOnWriteArrayListオブジェクトが含まれています.一方、CopyOnWriteArrayListは本質的に動的配列キューであるため、CopyOnWriteArraySetは動的配列によって実現される「集合」に相当する!CopyOnWriteArrayListでは重複する要素が許可されています.ただし、CopyOnWriteArraySetは集合であるため、重複集合はできません.したがって、CopyOnWriteArrayListはaddIfAbsent()とaddAllAbsent()の2つの追加要素のAPIを追加し、これらのAPIを通じて要素を追加する場合、要素が存在しない場合にのみ追加操作を実行します.CopyOnWriteArraySetの「スレッドセキュリティ」メカニズムは,CopyOnWriteArrayListと同様にvolatileと反発ロックによって実現される.これは前章でCopyOnWriteArrayListを紹介した際のデータ構造について説明したが,ここではこれ以上述べない.
 
CopyOnWriteArraySet関数リスト
//       set。
CopyOnWriteArraySet()
//          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                。
Iterator iterator()
//            set  ,     。
boolean remove(Object o)
//     set        collection       。
boolean removeAll(Collection> c)
//      set          collection     。
boolean retainAll(Collection> c)
//     set       。
int size()
//         set        。
Object[] toArray()
//         set        ;                  。
 T[] toArray(T[] a)


 
CopyOnWriteArraySetソースコード(JDK 1.7.0_40バージョン)
CopyOnWriteArraySet.JAvaの完全なソースコードは以下の通りです.
 
View Code
CopyOnWriteArraySetはCopyOnWriteArrayListによって実現され、そのAPIは基本的にCopyOnWriteArrayListのAPIを呼び出すことによって実現される.CopyOnWriteArrayListを知っていれば、CopyOnWriteArraySetの理解は水が流れることだと信じています.そこで,ここではCopyOnWriteArraySetのコードの詳細な解析は行わない.CopyOnWriteArrayListについて詳しくない場合は、「Javaマルチスレッドシリーズ--「JUCコレクション」02のCopyOnWriteArrayList」を参照してください.
 
CopyOnWriteArraySetの例
次に、HashSetとCopyOnWriteArraySetを一例で比較します.
import java.util.*;
import java.util.concurrent.*;

/*
 *   CopyOnWriteArraySet “    ”   , HashSet       。
 *
 *      “              set”   
 *   (01)  set CopyOnWriteArraySet   ,       。
 *   (02)  set HashSet   ,     ConcurrentModificationException  。
 *
 * @author skywang
 */
public class CopyOnWriteArraySetTest1 {

    // TODO: set HashSet   ,     。
    //private static Set set = new HashSet();
    private static Set set = new CopyOnWriteArraySet();
    public static void main(String[] args) {
    
        //          set    !
        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();
            }
        }
    }
}


実行結果:
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, 


結果説明:setはコレクションオブジェクトであるため、重複する要素は含まれません.ソースコードのsetをHashSetオブジェクトに変更すると、ConcurrentModificationException例外が発生します.
 
その他
1.Javaマルチスレッドシリーズ--「JUCコレクション」01のフレームワーク
2.Javaマルチスレッドシリーズ--「JUCコレクション」02のCopyOnWriteArrayLis
3.Javaマルチスレッドシリーズディレクトリ(共にxx編)
4.Javaコレクションシリーズディレクトリ(Category)