Here is a very simple illustrative and annotated producer consumer pattern example using C#, .NET 4.0, BlockingCollection and Tasks. The example sets up one producer thread on which it produces 100 integers and two consumer threads which each read that data off a common concurrent blocking queue. Although I use a BlockingCollection here it is backed internally by a concurrent queue.

using System; using System.Collections.Concurrent; using System.Threading.Tasks; namespace test { class Program { static void Main(string[] args) { Console.WriteLine(); // declare blocking collection backed by concurrent queue BlockingCollection<int> b = new BlockingCollection<int>(); // start consumer 1 which waits for data until available var consumer1 = Task.Factory.StartNew(() => { foreach (int data in b.GetConsumingEnumerable()) { Console.Write("c1=" + data + ", "); } }); // start consumer 2 which waits for data until available var consumer2 = Task.Factory.StartNew(() => { foreach (int data in b.GetConsumingEnumerable()) { Console.Write("c2=" + data + ", "); } }); // produce 100 integers on a producer thread var producer = Task.Factory.StartNew(() => { for (int i = 0; i < 100; i++) { b.Add(i); } b.CompleteAdding(); }); // wait for producer to finish producing producer.Wait(); // wait for all consumers to finish consuming Task.WaitAll(consumer1, consumer2); Console.WriteLine(); Console.WriteLine(); } } }

The output from running the program above is as follows. It’s basically consumer 1 and 2 interleaving as they read integers off the queue as they’re being produced.

c1=0, c1=2, c1=3, c1=4, c1=5, c1=6, c1=7, c1=8, c1=9, c1=10, c1=11, c1=12, c1=13, c1=14, c1=15, c1=16, c1=17, c1=18, c1=19, c2=1, c2=21, c2=22, c2=23, c2=24, c2 =25, c2=26, c2=27, c2=28, c2=29, c2=30, c2=31, c2=32, c2=33, c2=34, c2=35, c2=36, c2=37, c2=38, c2=39, c2=40, c2=41, c2=42, c2=43, c2=44, c2=45, c2=46, c2=47, c 2=48, c2=49, c2=50, c2=51, c2=52, c2=53, c2=54, c2=55, c2=56, c2=57, c2=58, c2=59, c2=60, c2=61, c2=62, c2=63, c2=64, c2=65, c2=66, c2=67, c2=68, c2=69, c2=70, c2=71, c2=72, c2=73, c2=74, c2=75, c2=76, c2=77, c2=78, c2=79, c2=80, c2=81, c2=82, c2=83, c2=84, c2=85, c2=86, c2=87, c2=88, c2=89, c2=90, c2=91, c2=92, c2=93, c2=94, c2=95, c2=96, c2=97, c2=98, c2=99, c1=20,

It’s somewhat sad and disheartening to see just how much further ahead C# is of Java in terms of the expressiveness and richness of the language. I personally really enjoyed using the lambdas above and I hope that with Java 8 the SDK libraries will grow to develop a more fluid and expressive style.