Well, this snippet isĀ from my old backup and let’s have a look for producer-consumer paradigm in action (in Java and .NET):
Have a look how join works in Java: http://www.barantopal.com/technology/multithreading-and-join/
import java.util.Stack;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 1 producer and 3 consumers producing/consuming 10 items
*
* @author pt
*
*/
public class ProducerConsumer {
Stack items = new Stack();
final static int NO_ITEMS = 10;
public static void main(String args[]) {
ProducerConsumer pc = new ProducerConsumer();
Thread t1 = new Thread(pc.new Producer());
Thread t2 = new Thread(pc.new Consumer());
Thread t3 = new Thread(pc.new Consumer());
Thread t4 = new Thread(pc.new Consumer());
t1.start();
try {
Thread.sleep(100);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
t2.start();
t3.start();
t4.start();
try {
t2.join();
t3.join();
t4.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
class Producer implements Runnable {
public void produce(int i) {
System.out.println("Producing " + i);
items.push(new Integer(i));
}
@Override
public void run() {
int i = 0;
// produce 10 items
while (i++ < NO_ITEMS) {
synchronized (items) {
produce(i);
items.notifyAll();
}
try {
// sleep for some time,
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
}
}
class Consumer implements Runnable {
AtomicInteger consumed = new AtomicInteger();
public void consume() {
if (!items.isEmpty()) {
System.out.println("Consuming " + items.pop());
consumed.incrementAndGet();
}
}
private boolean theEnd() {
return consumed.incrementAndGet() >= NO_ITEMS;
}
@Override
public void run() {
while (!theEnd()) {
synchronized (items) {
while (items.isEmpty() && (!theEnd())) {
try {
items.wait(10);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
consume();
}
}
}
}
}
Let’s do the similar in .NET:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ConsoleApp_ProducerConsumer
{
class Program
{
static void Main(string[] args)
{
Object lockObj = new object();
Queue queue = new Queue();
Producer p = new Producer(queue);
Comsumer c1 = new Comsumer(queue, lockObj, "c1");
Comsumer c2 = new Comsumer(queue, lockObj, "c2");
Thread t1 = new Thread(c1.consume);
Thread t2 = new Thread(c2.consume);
t1.Start();
t2.Start();
Thread t = new Thread(p.produce);
t.Start();
// keep console window open
Console.ReadLine();
}
}
public class Producer
{
Queue queue;
int productionCycleCounter;
public Producer(Queue queue)
{
this.queue = queue;
}
public void produce()
{
while (productionCycleCounter < 100)
{
productionCycleCounter += 1;// increase counter
string item = "item" + productionCycleCounter;
queue.Enqueue(item);
Console.WriteLine("Producing {0}", item);
}
}
}
public class Comsumer
{
Queue queue;
Object lockObject;
string name;
public Comsumer(Queue queue, Object lockObject, string name)
{
this.queue = queue;
this.lockObject = lockObject;
this.name = name;
}
public void consume()
{
Thread.Sleep(500);
string item;
while (true)
{
lock (lockObject)
{
if (queue.Count == 0)
{
continue;
}
item = queue.Dequeue();
Console.WriteLine(" {0} Comsuming {1}", name, item);
}
}
}
}
}