スレッドセーフコレクションの操作:ConcurrentStackおよびConcurrentQueue
スレッドセーフコレクションは、System.Collections.Concurrent名前空間の導入により.Net4で最初に導入されました。System.Collections.Concurrent名前空間のコレクションタイプには、スレッドセーフなコレクションクラスのコレクションが含まれています。
ConcurrentStack
スタックは、LIFO(後入れ先出し)ベースで機能するデータ構造です。ConcurrentStackクラスは、汎用Stackクラスのスレッドセーフな対応物です。ConcurrentStackは、.Net Framework 4の一部として最初に導入されたスレッドセーフなジェネリックコレクションクラスです。これは、可能な操作を示すこのクラスの重要なメソッドのリストです。
- Push(T element)-このメソッドは、タイプTのデータを追加するために使用されます。
- PushRange-このメソッドを使用して、タイプTのアイテムの配列を追加できます。
- TryPop(out T)-このメソッドは、スタックから最初の要素を取得するために使用されます。成功するとtrueを返し、それ以外の場合はfalseを返します。
- TryPeek(out T)-このメソッドは、スタックから次の要素を取得するために使用されますが、スタックから要素を削除することはありません。TryPop(out T)メソッドと同様に、成功した場合はtrueを返し、それ以外の場合はfalseを返すことに注意してください。
- 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クラスの重要なメソッドのリストです。
- Enqueue(T要素)-このメソッドは、タイプTのアイテムをキューに追加するために使用されます
- TryPeek(out T)-このメソッドは、キューから次の要素を取得するために使用されますが、キューから要素を削除することはありません。このメソッドは、成功した場合はtrueを返し、失敗した場合はfalseを返します。
- 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);
}