Javaスレッド(14):Concurrentパッケージ内の強力な同時集合クラス


ArrayList、HashMapなどの集合クラスを頻繁に使用する必要がありますが、これらの集合は同時実行メカニズムを実現することはできません.これにより、サーバ上で実行する際にリソースと時間を非常に消費し、これらの集合を反復する過程で操作できません.そうしないと、次のようなエラーが発生します.
public class CollectionModifyExceptionTest {
	public static void main(String[] args) {
		Collection users = new ArrayList();
		users.add(new User(" ",28));	
		users.add(new User(" ",25));			
		users.add(new User(" ",31));	
		Iterator itrUsers = users.iterator();
		while(itrUsers.hasNext()){
			System.out.println(" !");
			User user = (User)itrUsers.next();
			if(" ".equals(user.getName())){
				users.remove(user);
			} else {
				System.out.println(user);				
			}
		}
	}
}	

プログラムは、ArrayListタイプの集合を定義しているが、集合を反復するときにusersが現れるため、実行中にエラーが発生する.remove(user)は、集合からデータを削除することは、通常の集合では許されず、Java 5以降に現れるコンカレント集合クラスは、通常の集合ではコンカレントできない、反復中にデータを修正できないなどの問題に特化して現れる.
      
コンカレント・コレクション・クラスには、主に次のものがあります.
ConcurrentHashMap;          ConcurrentSkipListMap;              ConCurrentSkipListSet;           CopyOnWriteArrayList; CopyOnWriteArraySet;         ConcurrentLinkedQueue;
以下のいくつかの集合クラスについて簡単に説明します.
ConcurrentHashMapは、完全な同時取得と、所望の調整可能な同時ハッシュ・テーブルの更新をサポートします.このような方法は、Hashtableと同じ機能仕様を遵守し、Hashtableの各方法に対応する方法バージョンを含む.ただし、すべての操作はスレッドが安全であるにもかかわらず、検索操作はロックする必要はなく、すべてのアクセスを防止する方法でテーブル全体をロックすることはサポートされていません.このようなプログラムは、同期の詳細に関係なく、スレッドのセキュリティに依存してHashtableと完全に相互運用することができる.
主な構造方法は次のとおりです.
ConcurrentHashMap();  // 、  concurrencyLevel  。
ConcurrentHashMap(int initialCapacity);   // 、  concurrencyLevel  。
ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel);  // 、 。
ConcurrentHashMap(Map<> t);    // 。

ConcurrentLinkedQueueは、リンクノードベースの、境界のない、スレッドが安全なキューです.このキューはFIFO(先進先出)の原則に従って要素をソートし、キューのヘッダはキューの中で最も長い要素です.キューの末尾は、キュー内で最も時間が短い要素です.新しい要素がキューの末尾に挿入され、キュー取得操作はキューヘッダから要素を取得します.多くのスレッドが共通のcollectionにアクセスする場合、ConcurrentLinkedQueueはnull要素を許可しない適切な選択です. 
主な構造方法は次のとおりです.
ConcurrentLinkedQueue();  //  ConcurrentLinkedQueue。
ConcurrentLinkedQueue(Collection<> c);//   collection   ConcurrentLinkedQueue,  collection  

CopyOnWriteArrayListは、ArrayListのスレッドの安全な変形であり、すべての可変動作(追加、設定など)は、ベース配列を新しいコピーすることによって実現される.これは一般的に大きなオーバーヘッドを必要とするが、遍歴操作の数が可変操作の数を大幅に超える場合、この方法は他の代替方法よりも有効である可能性がある.同期ループはできないか、したくないが、同時スレッドから競合を排除する必要がある場合にも役立ちます.[スナップショット](Snapshot)スタイルの反復メソッドは、反復を作成するときに配列状態への参照を使用します.この配列は反復器の生存期間内には決して変更されないため、衝突は起こり得ず、反復器はConcurrentModificationExceptionを放出しないことを保証します.反復器を作成してから、反復器はリストの追加、削除、または変更を反映しません.反復器で要素を変更する操作(削除、設定、追加)はサポートされていません.これらの方法は、U n s p p p p o r t edOperationExceptionを放出します.
主な構造方法は次のとおりです.
CopyOnWriteArrayList();  //  。
CopyOnWriteArrayList(Collection<> c); //  Collection  ,  Collection  。
CopyOnWriteArrayList(E[] toCopyIn);   //  CopyOnWriteArrayList, 。

CopyOnWriteArraySetは、そのすべての操作に対してCopyOnWriteArrayListを使用するSetである.したがって、以下の基本プロパティを共有します.
  • setサイズが通常小さく維持され、読み取り専用操作が可変操作よりはるかに多く、遍歴中にスレッド間の衝突を防止する必要があるアプリケーションに最適です.
  • スレッドは安全です.
  • は、通常、ベース配列全体をコピーする必要があるため、可変操作(追加、設定、削除など)のオーバーヘッドが大きい.
  • 反復器では、可変除去操作はサポートされていません.
  • 反復器を使用して遍歴する速度は速く、他のスレッドと競合しません.反復器を構築するとき、反復器は不変の配列スナップショットに依存します. 

  • 主な構築方法は次のとおりです.
    CopyOnWriteArraySet();   //  set
    CopyOnWriteArraySet(Collection<> c);   //  Collection   set
    

           
    同時集合クラスについて説明した後、本明細書の最初の例に戻ると、Collection users=new ArrayList()Collection users=new CopyOnWriteArrayList()に書き換えます.プログラムを再実行すると、プログラムは正常に行われ、結果は以下の通りです.
     !
    {name:' ',age:28}
     !
     !
    {name:' ',age:31}