jdk 5および発注中のCopyOnWriteクラスの使い方


jdk 5のconcurrentパッケージには、CopyOnWriteHashMap、CopyOnWriteArrayList、CopyOnWriteArraySetなど、いくつかのCopyOnWriteの先頭クラスが追加されています.copy-on-writeモードは、オブジェクトの一貫性スナップショットを維持するために、異なるが関連する属性を協調的に読み取る際に必要な同期を、可変性(immutability)に依存して除去することを宣言した.集合の場合、これは、大量の読み取り(すなわち、get())および反復がある場合、たまに書き込み(すなわち、add())呼び出しの世話をするために同期動作を必要としないことを意味する.新しいCopyOnWriteArrayListクラスとCopyOnWriteArraySetクラスでは、すべての可変操作がまずバックグラウンド配列のコピーを取得し、コピーを変更し、コピーを置き換えます.このアプローチは、自身の変更された集合を遍歴するときに、ConcurrentModificationExceptionを決して投げ出さないことを保証します.巡回集合は元の集合で完了し,以降の操作では更新後の集合を使用する.これらの新しい集合、CopyOnWriteArrayListおよびCopyOnWriteArraySetは、読み取り動作が通常、書き込み動作を大幅に上回る場合に最適である.
以下に示すように、集合の使用は、それらの非copy−on−write置換物と全く同じである.コレクションを作成し、要素を追加または削除するだけです.オブジェクトが集合に加わったとしても,元のIteratorを行い,元の集合の中の項目を巡り続けることができる.
 
import java.util.*;
import java.util.concurrent.*;
public class CopyOnWrite {
  public static void main(String args[]) {
    List list1 = new CopyOnWriteArrayList(Arrays.asList(args));
    List list2 = new ArrayList(Arrays.asList(args));
    Iterator itor1 = list1.iterator();
    Iterator itor2 = list2.iterator();
    list1.add("New");
    list2.add("New");
    try {
      printAll(itor1);
    } catch (ConcurrentModificationException e) {
      System.err.println("Shouldn't get here");
    }
    try {
      printAll(itor2);
    } catch (ConcurrentModificationException e) {
      System.err.println("Will get here.");
    }
  }
  private static void printAll(Iterator itor) {
    while (itor.hasNext()) {
      System.out.println(itor.next());
    }
  }
}

この例示的なプログラムは、コマンドラインパラメータを用いてCopyOnWriteArrayListおよびArrayListの2つのインスタンスを作成する.各例のIteratorが得られた後に、それぞれ1つの要素が加えられる.ArrayList反復がConcurrentModificationExceptionの問題によって直ちに停止すると、CopyOnWriteArrayList反復は、iteratorが得られた後に元の集合が変化したため、異常を投げ出すことなく継続することができる.この動作(イベントリスナーのセット内のすべての要素を通知するなど)が必要な場合は、copy-on-writeセットを使用することが望ましい.使用しない場合は、元のものを使用し、異常が発生した場合に処理することを保証します.
 
[1].驯服Tiger:并行集合http://www.ibm.com/developerworks/cn/java/j-tiger06164/