Csharp/CSharp Tutorial/Thread/Producer Consumer

Материал из .Net Framework эксперт
Перейти к: навигация, поиск

Consumer Producer with Monitor

using System;
using System.Threading;
public class MyData {
    private double _pi = 0.0;
    private int _iterations = 0;
    private bool _valueReady = false;
    public void WriteData(int iterations, double val) {
        lock (this) {
            if (_valueReady) {
                Monitor.Wait(this);
            }
            _pi = val;
            _iterations = iterations;
            _valueReady = true;
            Monitor.Pulse(this);
        }
    }
    public void ReadData(out int iterations, out double val) {
        lock (this) {
            if (!_valueReady) {
                Monitor.Wait(this);
            }
            val = _pi;
            iterations = _iterations;
            _valueReady = false;
            Monitor.Pulse(this);
        }
    }
}
class MyProducer {
    private MyData _pi;
    private int TotalIters;
    public MyProducer(MyData pi, int iterations) {
        _pi = pi;
        TotalIters = iterations;
    }
    public Thread CreateProducerThread() {
        return new Thread(new ThreadStart(this.calculate));
    }
    private void calculate() {
        int iters = 1;
        do {
            iters += 4;
            _pi.WriteData(iters, iters * 4);
        } while (iters < TotalIters);
    }
}
class MyConsumer {
    private MyData _pi;
    private int TotalIters;
    public MyConsumer(MyData pi, int iterations) {
        _pi = pi;
        TotalIters = iterations;
    }
    public Thread CreateConsumerThread() {
        return new Thread(new ThreadStart(this.printValues));
    }
    private void printValues() {
        int iters = new int();
        double pi = new double();
        do {
            _pi.ReadData(out  iters, out pi);
            System.Console.WriteLine("Iters: {0}\tPi:  {1}",iters.ToString(), pi.ToString());
        } while (iters < TotalIters);
    }
}
class MainClass {
    static void Main(string[] args) {
        MyData pi = new MyData();
        MyProducer prod = new MyProducer(pi, 100000);
        Thread producerThread = prod.CreateProducerThread();
        MyConsumer cons = new MyConsumer(pi, 100000);
        Thread consumerThread = cons.CreateConsumerThread();
        producerThread.Start();
        consumerThread.Start();
        producerThread.Join();
        consumerThread.Join();
    }
}

Philosopher Example

using System;
using System.Threading;
class PhilosopherExample {
    public static bool chopStick1Available = true;
    public static bool chopStick2Available = true;
    public static void Main() {
        Thread philosopher1 = new Thread(new ThreadStart(GetChopSticks1));
        Thread philosopher2 = new Thread(new ThreadStart(GetChopSticks2));
        philosopher1.Start();
        philosopher2.Start();
    }
    public static void GetChopSticks1() {
        while (!chopStick1Available) {
            Console.WriteLine("#1 waiting for 1st");
            Thread.Sleep(100);
        }
        Console.WriteLine("#1 got 1st");
        chopStick1Available = false;
        while (!chopStick2Available) {
            Console.WriteLine("#1 waiting for 2nd");
            Thread.Sleep(100); 
        }
        Console.WriteLine("#1 got 2nd");
        chopStick2Available = false;
        Console.WriteLine("#1 uses and releases chopsticks.");
        chopStick1Available = true;
        chopStick2Available = true;
    }
    public static void GetChopSticks2() {
        while (!chopStick2Available) {
            Console.WriteLine("#2 waiting for 1st");
            Thread.Sleep(100);
        }
        Console.WriteLine("#2 got 1st chopstick.");
        chopStick2Available = false;
        while (!chopStick1Available) {
            Console.WriteLine("#2 waiting for 2nd");
            Thread.Sleep(100);
        }
        Console.WriteLine("#2 got 2nd chopstick.");
        chopStick1Available = false;
        Console.WriteLine("#2 uses and releases chopsticks.");
        chopStick1Available = true;
        chopStick2Available = true;
    }
}

Producer and consumer

/*
Quote from 
C# and the .NET Framework
by Bob Powell 
*/
using System;
using System.Threading;
public class Factory {
  private int[]  Widgets = new int[100];
  private int    WidgetIndex = 0;
  private AutoResetEvent NewWidgetEvent = new AutoResetEvent( false );
  protected void Producer( ) {
    while( true ) {
      lock( this ) {
        if( WidgetIndex < 100 ) {
          Widgets[ WidgetIndex ] = 1;
          Console.WriteLine("Widget {0} Produced", WidgetIndex++ );
          NewWidgetEvent.Set( );
        }
      }
      Thread.Sleep( (new Random()).Next( 5 ) * 1000 );
    }
  }
  protected void Consumer( ) {
    while( true ) {
      NewWidgetEvent.WaitOne( );
      int iWidgetIndex = 0;
      lock( this ) {
        iWidgetIndex = --this.WidgetIndex;
        Console.WriteLine("Consuming widget {0}", iWidgetIndex );  
        Widgets[ iWidgetIndex-- ] = 0;
      }
    }
  }
  public void Run( ) {
    for( int i = 0; i < 3; i++ ) {
      Thread producer = new Thread( new ThreadStart( Producer ) );
      producer.Start( );
    }
    for( int i = 0; i < 3; i++ ) {
      Thread consumer = new Thread( new ThreadStart( Consumer ) );
      consumer.Start( );
    }
  }

  public static void Main( ) {
    Factory factory = new Factory( );
    factory.Run( );
  }
}
Widget 0 Produced
Widget 1 Produced
Widget 2 Produced
Consuming widget 2
Widget 2 Produced
Consuming widget 2
Widget 2 Produced
Widget 3 Produced
Consuming widget 3
Consuming widget 2
Widget 2 Produced
Consuming widget 2
Widget 2 Produced
Widget 3 Produced
Consuming widget 3
Consuming widget 2
Widget 2 Produced
Consuming widget 2
^CTerminate batch job (Y/N)? n

Producer/consumer

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime;
using System.Runtime.rupilerServices;
using System.Security;
using System.Text;
using System.Threading;
public class MainClass
{
    private static Queue<string> sharedQueue = new Queue<string>();    
    public static void Main()
    {
        Thread t1 = new Thread(Producer);
        Thread t2 = new Thread(Consumer);
        t1.Start();
        t2.Start();
        // Join on them:
        t1.Join();
        t2.Join();
    }
    private static void Producer()
    {
        for (int i = 0; i < 2; i++)
        {
            string item = "Item#" + i;
            lock (sharedQueue)
            {
                sharedQueue.Enqueue(item);
                Monitor.Pulse(sharedQueue);
            }
        }
    }
    private static void Consumer()
    {
        for (int i = 0; i < 2; i++)
        {
            string item = null;
            lock (sharedQueue)
            {
                while (sharedQueue.Count == 0)
                    Monitor.Wait(sharedQueue);
                item = sharedQueue.Dequeue();
            }
            Console.WriteLine("Processing item: {0}", item);
        }
    }
}
Processing item: Item#0
Processing item: Item#1