using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ThreadTestProject
{
//LetSynchronized用来存放和取出缓冲区变量
public class LetSynchronized
{
//定义了只有三个字节的缓冲区
private int[] buffer =new int[1];
//确认缓冲区内已放数值的个数
private int bufferCount = 0;
//确定读写的位置
private int readLocation = 0, writeLocation = 0;
public LetSynchronized()
{
}
public int getBuffer()
{
//加上了共享锁
lock (this)
{
//判断如果缓冲区内无内容,则Consumer进入wait状态,并且释放对象锁
if (bufferCount == 0)
{
Console.WriteLine("缓冲区无数据,消费者无法读取");
Monitor.Wait(this);
}
//Thread.Sleep(1000);
int readValue = buffer[readLocation];
//已经从缓冲区读取了内容,所以bufferCount要进行自减.
bufferCount--;
//求余的目的是为了循环使用缓冲区
readLocation = (readLocation + 1) % buffer.Length;
//通知对象的第一个等待线程可以从WaitSleepJoin转换到Started状态.
Monitor.Pulse(this);
//返回给consumer取出的数值
return readValue;
}
}
//将数据放入缓冲区
public void setBuffer(int writeValue)
{
//锁住共享数据区
lock (this)
{
//如果缓冲区已满,那么进入waitsleepjoin状态
if (bufferCount == buffer.Length)
{
Console.WriteLine("缓冲区满了,等待消费...!");
Monitor.Wait(this);
}
//Thread.Sleep(1000);
//向缓冲区写入数据
buffer[writeLocation] = writeValue;
//自加,代表缓冲区现在到底有几个数据
bufferCount++;
//用%实现缓冲区的循环利用
writeLocation = (writeLocation + 1) % buffer.Length;
//唤醒waitSleepJoin状态的进程,到started状态
Monitor.Pulse(this);
//使用lock隐式的释放了共享锁
}
}
}
//生产者类,向缓冲区中放入数据
public class Producer
{
//定义了同步变量
LetSynchronized shared;
//此处构造函数的作用是在启动类中调用Producer的时候,把启动类中定义的sharedLocation传过来
public Producer(LetSynchronized sharedLocation)
{
shared = sharedLocation;
}
//定义生产过程
public void produce()
{
//将数据放入缓冲区
for (int count = 1; count <= 5; count++)
{
shared.setBuffer(count);
Console.WriteLine("生产者向缓冲区中写入 " + count);
}
//得到当前线程的名字
string name = Thread.CurrentThread.Name;
//此线程执行完毕
Console.WriteLine(name + "生产完毕!");
}
}
//定义消费者类
public class Consumer
{
private int value;
//定义同步变量
LetSynchronized shared;
//定义构造函数,负责传递启动类中的shared
public Consumer(LetSynchronized sharedLocation)
{
shared = sharedLocation;
}
//从缓冲区中循环读取
public void consume()
{
for (int count = 1; count <= 5; count++)
{
value = shared.getBuffer();
Console.WriteLine("消费者从缓冲中读取了数据 " + value);
}
//取得当前线程的名字
string name = Thread.CurrentThread.Name;
Console.WriteLine(name + "消费完毕");
}
}
//设置为启动类
public class ThreadTest
{
public static void Main()
{
LetSynchronized shared = new LetSynchronized();
//初始化了生产者和消费者,并且把shared参数传递了过去
Producer producer1 = new Producer(shared);
Consumer consumer1 = new Consumer(shared);
//定义了一个producerThread线程,new Thread是构造Thread
//后面的那个new 则是启动一个新的线程,线程启动的方法是producer1.produce
Thread producerThread = new Thread(new ThreadStart(producer1.produce));
producerThread.Name = "生产者";
//同上
Thread consumerThread = new Thread(new ThreadStart(consumer1.consume));
consumerThread.Name = "消费者";
//启动这两个线程
producerThread.Start();
consumerThread.Start();
}
}
}
生产者与消费者问题
最新推荐文章于 2024-06-01 07:30:00 发布