在 C# 中管理线程关系
现在,我正在学习多线程及其在 C# 中的用法。所以,我面临如下问题: (抱歉我的问题如此简单)
假设我们有两个名为 Producer 和 Consumer 的类。生产者任务在程序运行时生成 4 个数字,消费者任务正在消耗并使用这些数字,并在程序结束时返回它们的总和。
Consumer 类定义:
class Consumer
{
private HoldInteger sharedLocation;
private Random randomSleepTime;
public Consumer(HoldInteger shared, Random random)
{
sharedLocation = shared;
randomSleepTime = random;
}
public void Consume()
{
int sum = 0;
for (int i = 1; i <= 4; i++)
{
Thread.Sleep(randomSleepTime.Next(1, 3000));
sum += sharedLocation.Buffer;
}
}
}
Producer 类的定义如下:
class Producer
{
private HoldInteger sharedLocation;
private Random randomSleepTime;
public Producer(HoldInteger shared, Random random)
{
sharedLocation = shared;
randomSleepTime = random;
}
public void Produce()
{
for (int i = 1; i <= 4; i++)
{
Thread.Sleep(randomSleepTime.Next(1, 3000));
sharedLocation.Buffer = i;
}
}
}
另外,我们有 HoldInteger
类包含 Buffer 变量,生产者写入此变量,消费者从中读取。我组合这些类并在我的主方法中编写以下代码:
static void Main(string[] args)
{
HoldInteger holdInteger = new HoldInteger();
Random random = new Random();
Producer producer = new Producer(holdInteger, random);
Consumer consumer = new Consumer(holdInteger, random);
Thread producerThread = new Thread(new ThreadStart(producer.Produce));
producerThread.Name = "producer";
Thread consumerThread = new Thread(new ThreadStart(consumer.Consume));
consumerThread.Name = "consumer";
producerThread.Start();
consumerThread.Start();
}
所以,我的问题是如何管理这种与低内存和浪费时间的关系?
请注意,这些线程管理代码将是放置在 HoldInteger
类主体中。
感谢您的关注。
Now, i am learning multi-threading and usage of it in C#. So, i face the problem as below:
(Sorry for my so simple question)
Suppose that, we have two classes named Producer and Consumer. Producer task is producing 4 numbers while program running and Consumer task is consuming and using those numbers and return the sum of them at the end of program.
Consumer Class definition:
class Consumer
{
private HoldInteger sharedLocation;
private Random randomSleepTime;
public Consumer(HoldInteger shared, Random random)
{
sharedLocation = shared;
randomSleepTime = random;
}
public void Consume()
{
int sum = 0;
for (int i = 1; i <= 4; i++)
{
Thread.Sleep(randomSleepTime.Next(1, 3000));
sum += sharedLocation.Buffer;
}
}
}
and the definition of Producer Class is as below :
class Producer
{
private HoldInteger sharedLocation;
private Random randomSleepTime;
public Producer(HoldInteger shared, Random random)
{
sharedLocation = shared;
randomSleepTime = random;
}
public void Produce()
{
for (int i = 1; i <= 4; i++)
{
Thread.Sleep(randomSleepTime.Next(1, 3000));
sharedLocation.Buffer = i;
}
}
}
And also, we have HoldInteger
class contains Buffer variable that producer write this variable and consumer read from that. I combine these classes and program the below code in my main method:
static void Main(string[] args)
{
HoldInteger holdInteger = new HoldInteger();
Random random = new Random();
Producer producer = new Producer(holdInteger, random);
Consumer consumer = new Consumer(holdInteger, random);
Thread producerThread = new Thread(new ThreadStart(producer.Produce));
producerThread.Name = "producer";
Thread consumerThread = new Thread(new ThreadStart(consumer.Consume));
consumerThread.Name = "consumer";
producerThread.Start();
consumerThread.Start();
}
So, my question is that How can i manage this relationship With Low Memory and Time Wasting ?
Please note that, these threads management code will be placed in HoldInteger
class body.
Thanks for your attention.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我将用
BlockingQueue
替换HoldInteger
类,你可以找到一个此处实现,有关实现背后原因的更多详细信息,检查这个问题。我认为.NET 4.0 也可能有一个阻塞队列。这种方法随后将使事情变得更容易管理:您的消费者现在看起来像这样:
但是,如果您想保留
HoldInteger
(如果这是某种要求),那么您可以放置在HoldIntegerUnsynchronized
类中使用阻塞队列而不是使用缓冲区(应该很简单),您将获得相同的结果。注意:使用这种方法,您不再需要担心丢失值或读取过时的值,因为线程不会在正确的时间唤醒。这是使用“缓冲区”的潜在问题:
即使您的整数持有者确实安全地处理了底层“缓冲区”,您仍然不能保证您将获得您想要的所有整数。考虑到这一点:
情况 1
情况 2
由于计时器不够精确,这种情况完全有可能发生,在第一种情况下,它会导致消费者读取一个过时的值,而在第二种情况下,它将导致消费者错过一个值。
I would replace the
HoldInteger
class with aBlockingQueue
, you can find an implementation here and for more details on the reason behind the implementation, check this question. I think .NET 4.0 might have a blocking queue too. This approach will subsequently make things a lot easier to manage:Your consumer will look like this now:
However, if you want to keep the
HoldInteger
(if this is some sort of requirement), then you can place the blocking queue inside theHoldIntegerUnsynchronized
class instead of having a buffer (should be trivial to do) and you will achieve the same result.Note: with this approach you no longer have to worry about missing a value or reading a stale value because the threads don't wake up at exactly the right time. Here is the potential problem with using a "buffer":
Even if your integer holder does handle the underlying "buffer" safely, you are still not guaranteed that you will get all the integers that you want. Take this into consideration:
Case 1
Case 2
Since the timer is not precise enough, this sort of thing is entirely possible and in the first case it will cause the consumer to read a stale value, while in the second case it will cause the consumer to miss a value.
您可以执行类似
“注意我尚未测试此代码!”之类的操作!
You can do something like
Note I haven't tested this code!