public void MultiThreadEnqueue() { const int capacity = 1000000; const int threadsCount = 100; const int count = capacity / threadsCount; var target = new ConcurrentPriorityQueue<DateTime>(); var execStats = new ExecWithStats[threadsCount]; var watcher = new Stopwatch(); // several threads enqueue elements watcher.Start(); Parallel.For(0, threadsCount, index => { execStats[index] = new ExecWithStats(string.Format("Add {0}", count), count, () => target.Add(new DateTime())); execStats[index].Exec(); }); watcher.Stop(); Assert.AreEqual(capacity, target.Count); Console.WriteLine("{0} threads each enqueue {1} elements. total time: {2}\n", threadsCount, count, watcher.Elapsed); ExecWithStats.OutputStatsSummary(execStats); // several threads dequeue elements watcher.Start(); Parallel.For(0, threadsCount, index => { execStats[index] = new ExecWithStats(string.Format("Take {0}", count), count, () => target.Take()); execStats[index].Exec(); }); watcher.Stop(); Assert.AreEqual(0, target.Count); Console.WriteLine("\n{0} threads each dequeue {1} elements. total time: {2}\n", threadsCount, count, watcher.Elapsed); ExecWithStats.OutputStatsSummary(execStats); }
public void RaceWithStats() { const int capacity = 1000000; const int threadsCount = 100; const int count = capacity / threadsCount; var target = new ConcurrentPriorityQueue<DateTime>(); var execStats = new List<ExecWithStats>(); var threadWait = new CountdownEvent(threadsCount); // odd threads will enqueue elements, while even threads will dequeue // obviously there will be a race condition and especially in the beginning dequeue will throw, because queue will often be empty // the total number of exceptions on dequeue threads will correspond the the number of items left in the queue for (var i = 0; i < threadsCount; i++) { ExecWithStats exec; if (i % 2 != 0) { exec = new ExecWithStats(string.Format("Add {0} elements", count), count, () => target.Add( new DateTime()), threadWait); } else { exec = new ExecWithStats(string.Format("Take {0} elements", count), count, () => target.Take(), threadWait); } execStats.Add(exec); var thread = new Thread(() => exec.Exec()); thread.Start(); } // Wait for all threads in pool to calculate. threadWait.Wait(); // Output stats summary ExecWithStats.OutputStatsSummary(execStats); // Output queue state Console.WriteLine("Queue count:{0}, capacity:{1}", target.Count, target.Capacity); // Un-comment for a detailed list of stats //Console.WriteLine("---------------------"); //foreach (var execStat in execStats) //{ // var stats = execStat.GetStats(); // Console.WriteLine("Name:{0}, Min: {1}, Median: {2}, Max {3}, Exceptions: {4}", stats.Name, stats.Min, stats.Med, stats.Max, stats.ExceptionsCount); //} }