【发布时间】:2020-07-16 04:22:54
【问题描述】:
我有三个线程应该将一个随机 int 添加到队列中,第四个线程将 int 出队,第五个线程打印其中的数字。我正在使用线程,因为在该程序的范围内最终将需要它们并将更多的数字入队/出队,但是在生成随机整数时会遇到问题。我正在使用 RandomGenerator 类来创建数字,并创建此类的实例,然后调用其 GetRandom 方法将 int 字段设置为随机数。然后,我将此字段传递给前三个线程,这些线程调用该方法进行排队。打印的 int 不是随机的,我意识到这是因为我只是在程序开始时调用该方法并将相同的确切数字传递给所有三个线程。我对 C# 比较陌生,并意识到我可能犯了一个基本错误。我还意识到第四个线程有时会在队列为空时访问队列,但目前并不那么重要。我已经尝试了许多不同的方法,并且还可以在 Program 类中使用数字生成器。代码如下:
...
class Program
{
static void Main()
{
Program p = new Program();
RandomGenerator rg = new RandomGenerator();
Queue<int> numberQueue = new Queue<int>();
int randomNumber = rg.GetRandom(1, 10);
Thread T1 = new Thread(delegate () { p.EnqueueNumber(numberQueue, randomNumber); });
Thread T2 = new Thread(delegate () { p.EnqueueNumber(numberQueue, randomNumber); });
Thread T3 = new Thread(delegate () { p.EnqueueNumber(numberQueue, randomNumber); });
Thread T4 = new Thread(delegate () { p.DequeueNumber(numberQueue); });
Thread T5 = new Thread(delegate () { p.PrintNumbers(numberQueue); });
T1.Start();
T2.Start();
T3.Start();
T4.Start();
T5.Start();
T1.Join();
T2.Join();
T3.Join();
T4.Join();
T5.Join();
}
public void EnqueueNumber(Queue<int> numberQueue, int randomNumber)
{
numberQueue.Enqueue(randomNumber);
}
public void DequeueNumber(Queue<int> numberQueue)
{
numberQueue.Dequeue();
}
public void PrintNumbers(Queue<int> numberQueue)
{
foreach (int i in numberQueue)
{
Console.Write(i);
}
Console.ReadKey();
}
}
public class RandomGenerator
{
private static Random _random = new Random();
private static object syncLock = new object();
public int GetRandom(int min, int max)
{
lock (syncLock)
{
return _random.Next(min, max);
}
}
}
...
【问题讨论】:
-
小心线程安全。
Queue类不是线程安全的。另请注意,您尝试实现的模式称为“生产者-消费者”模式,并且 .NET 平台包含用于轻松且稳健地实现此模式的专用工具。你可以看看BlockingCollection类的例子,它不是最好的,但它是最容易学习的。 -
我会考虑查看
[ThreadStatic] private static Random _random = new Random();,因为这样在获取随机数时就不需要lock。 -
@Enigmativity 是的,但代价是为每个线程创建一个
Random实例。也许没什么大不了的,但重要的是要知道。
标签: c# multithreading random int queue