Java
 Computer >> コンピューター >  >> プログラミング >> Java

Javaでコレクションをスレッドセーフにする方法

java.utilパッケージのCollectionsクラスには、コレクション専用に動作するユーティリティメソッドが多数用意されており、ポリモーフィックなアルゴリズムを含むさまざまな追加操作を利用できます。

マルチスレッド環境でコレクションを安全に扱いたい場合、このクラスが提供する同期化メソッドを使うことで、既存のコレクションを簡単にスレッドセーフなものへ変換できます。以下に、synchronizedCollection()系メソッドの主なバリアントを示します。

No.メソッドと説明
1 static <T> Collection<T> synchronizedCollection(Collection<T> c)
任意のコレクションオブジェクトを受け取り、指定されたコレクションを基盤とする同期済み(スレッドセーフ)のコレクションを返します。
2 static <T> List<T> synchronizedList(List<T> list)
Listインターフェースのオブジェクトを受け取り、指定されたリストを基盤とする同期済み(スレッドセーフ)のリストを返します。
3 static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)
Mapインターフェースのオブジェクトを受け取り、指定されたマップを基盤とする同期済み(スレッドセーフ)のマップを返します。
4 static <T> Set<T> synchronizedSet(Set<T> s)
Setインターフェースのオブジェクトを受け取り、指定されたセットを基盤とする同期済み(スレッドセーフ)のセットを返します。
5 static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)
SortedMapインターフェースのオブジェクトを受け取り、指定されたソート済みマップを基盤とする同期済み(スレッドセーフ)のソート済みマップを返します。
6 static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)
SortedSetインターフェースのオブジェクトを受け取り、指定されたソート済みセットを基盤とする同期済み(スレッドセーフ)のソート済みセットを返します。

使用例

ここでは、Vectorオブジェクトを作成し、Collections.synchronizedCollection()メソッドを使って同期化されたコレクションを取得する例を紹介します。

import java.util.Collection;
import java.util.Collections;
import java.util.Vector;

public class CollectionSynchronizedExample {
   public static void main(String[] args) {
      // Vectorオブジェクトのインスタンス化
      Vector<String> vector = new Vector<String>();
      vector.add("JavaFx");
      vector.add("Java");
      vector.add("WebGL");
      vector.add("OpenCV");

      System.out.println(vector);

      // コレクションを同期化して取得
      Collection<String> synchronizedVector = Collections.synchronizedCollection(vector);
      System.out.println("Synchronized " + synchronizedVector);

      // 同期化されたコレクションへの要素追加
      synchronizedVector.add("CoffeeScript");
   }
}

実行結果

[JavaFx, Java, WebGL, OpenCV]
Synchronized [JavaFx, Java, WebGL, OpenCV]

注意点:イテレーション時の手動同期

Collections.synchronizedXXX()で生成されたコレクションは、個々の操作(add、removeなど)についてはスレッドセーフですが、イテレータによる繰り返し処理は自動的には同期されません。複数スレッドから同時に走査する場合は、次のように明示的に同期ブロックで囲む必要があります。

Collection<String> c = Collections.synchronizedCollection(vector);
synchronized (c) {
   for (String item : c) {
      System.out.println(item);
   }
}

また、より高度な並行処理が必要な場合は、java.util.concurrentパッケージのConcurrentHashMapCopyOnWriteArrayListなど、最初からスレッドセーフとして設計されたコレクションクラスの利用も検討するとよいでしょう。

  1. Twitterでスレッド(連続ツイート)を作成する方法|投稿手順とコツを解説

    押さえておきたいポイント新しいツイートを作成し、右下の青い「+」アイコンを選択すると、2つ目のツイートを書き始められます。スレッドが完成するまでこれを繰り返しましょう。投稿する準備ができたら「すべてツイート」を選択します。スレッド内のツイート数を「1/5」「2/5」のように各ツイートに記載するのが、Twitterで一般的なマナーとされています。この記事では、Twitterのスレッド(連続ツイート)の作成方法を解説します。スレッドとは、複数のツイートがつながり、ひとつの連続した投稿として読めるものです。1つのツイートの文字数制限では伝えきれないアイデアや考えを詳しく説明したいときに活用できます。

  2. Javaで列挙型(enum)を使ってシングルトンを実装する方法

    シングルトンパターンとは、あるクラスのインスタンス生成を1つのオブジェクトだけに制限するデザインパターンです。enumでシングルトンを実装する場合、INSTANCEがその役割を担い、これはenumの唯一のインスタンスを表すpublic static finalフィールドです。 EnumSingleton.INSTANCEのように直接アクセスしてインスタンスを取得することも可能ですが、将来的に実装を変更することを見越して、getterメソッドでカプセル化しておくのがより良い設計とされています。 enumをシングルトンとして使うメリット Javaでenumをシングルトンとして採用する主な理由は以