スレッドセーフコレクションの操作:ConcurrentStackおよびConcurrentQueue

スレッドセーフコレクションは、System.Collections.Concurrent名前空間の導入により.Net4で最初に導入されました。System.Collections.Concurrent名前空間のコレクションタイプには、スレッドセーフなコレクションクラスのコレクションが含まれています。

ConcurrentStack

スタックは、LIFO(後入れ先出し)ベースで機能するデータ構造です。ConcurrentStackクラスは、汎用Stackクラスのスレッドセーフな対応物です。ConcurrentStackは、.Net Framework 4の一部として最初に導入されたスレッドセーフなジェネリックコレクションクラスです。これは、可能な操作を示すこのクラスの重要なメソッドのリストです。

  1. Push(T element)-このメソッドは、タイプTのデータを追加するために使用されます。
  2. PushRange-このメソッドを使用して、タイプTのアイテムの配列を追加できます。
  3. TryPop(out T)-このメソッドは、スタックから最初の要素を取得するために使用されます。成功するとtrueを返し、それ以外の場合はfalseを返します。
  4. TryPeek(out T)-このメソッドは、スタックから次の要素を取得するために使用されますが、スタックから要素を削除することはありません。TryPop(out T)メソッドと同様に、成功した場合はtrueを返し、それ以外の場合はfalseを返すことに注意してください。
  5. TryPopRange-このメソッドはオーバーロードされ、TryPopと同様に機能しますが、スタックから配列を取得するために使用されます

ConcurrentStackクラスのインスタンスを作成し、それにデータをプッシュする方法は次のとおりです。

ConcurrentStack concurrentStack = new ConcurrentStack();

for (Int32 index = 0; index < 10; index++)

{

       concurrentStack.Push(index);

}

並行スタックから要素を取得するには、以下に示すように、TryPop(out T)メソッドを利用できます。

Int32 data;

bool success = concurrentStack.TryPop(out data);

次のコードリストは、並行スタックとの間でデータを格納および取得する方法を示しています。

static void Main(string[] args)

       {

           ConcurrentStack concurrentStack = new ConcurrentStack();

           for (Int32 index = 0; index < 100; index++)

           {

               concurrentStack.Push(index);

           }

           while (concurrentStack.Count > 0)

           {

               Int32 data;

               bool success = concurrentStack.TryPop(out data);

               if (success)

              {

                   Console.WriteLine(data);

               }

           }

           Console.Read();

       }

上記のコード一覧を実行すると、コンソールウィンドウに0から99までの数字が逆の順序で表示されます。

ConcurrentQueue

キューは、FIFO(先入れ先出し)に基づいて機能するデータ構造です。.NetのConcurrentQueueクラスは、スレッドセーフなFIFOベースの汎用キューとして機能します。

以下は、ConcurrentQueueクラスの重要なメソッドのリストです。

  1. Enqueue(T要素)-このメソッドは、タイプTのアイテムをキューに追加するために使用されます
  2. TryPeek(out T)-このメソッドは、キューから次の要素を取得するために使用されますが、キューから要素を削除することはありません。このメソッドは、成功した場合はtrueを返し、失敗した場合はfalseを返します。
  3. TryDequeue(out T)-このメソッドは、キューから最初の要素を取得するために使用されます。TryPeek(out T)メソッドとは異なり、キューから要素を削除します。このメソッドは、成功した場合はtrueを返し、それ以外の場合はfalseを返します。

次のコードスニペットは、整数を格納するためのConcurrentQueueクラスのインスタンスを作成する方法を示しています。

ConcurrentQueue concurrentQueue = new ConcurrentQueue();

要素を並行キューインスタンスに格納するには、以下に示すようにEnqueueメソッドを利用できます。

concurrentQueue.Enqueue(100);

次のコードリストは、並行キューとの間で要素を格納および取得する方法を示しています。

ConcurrentQueue concurrentQueue = new ConcurrentQueue();

for (int index = 0; index < 100; index++)

{

     concurrentQueue.Enqueue(index);

}

Int32 item;

while (concurrentQueue.TryDequeue(out item))

{

     Console.WriteLine(item);

}

上記のコード一覧を実行すると、コンソールウィンドウに0〜99の数字が表示されます。

ConcurrentStackクラスとConcurrentQueueクラスはどちらもスレッドセーフであり、ロックと同期の問題を内部で管理できることに注意してください。

ToArray()メソッドを呼び出すことにより、並行キューインスタンスを配列に変換することもできます。次のコードスニペットは、これを実現する方法を示しています。

ConcurrentQueue concurrentQueue = new ConcurrentQueue();

for (Int32 index = 0; index < 100; index++ )

   concurrentQueue.Enqueue(index);

Int32[] integerArray = concurrentQueue.ToArray();

foreach (int i in integerArray)

{

   Console.WriteLine(i);

}

ConcurrentQueueクラスのIsEmptyプロパティは、コレクションが空の場合はtrueを返し、それ以外の場合はfalseを返します。次のコードスニペットは、このメソッドの使用方法を示しています。

ConcurrentQueue concurrentQueue = new ConcurrentQueue();

for (Int32 index = 0; index < 100; index++ )

concurrentQueue.Enqueue(index);

while(!concurrentQueue.IsEmpty)

{

     Int32 result;

     concurrentQueue.TryDequeue(out result);

     Console.WriteLine(result);

}