我有简单的类生成随机数:
public class Bar
{
Random rnd = new Random();
public int GenerateRandomNumber()
{
return rnd.Next(1, 100);
}
}
然后我在第二课中使用它,我创建了两个线程。每个线程都使用bar类中的函数在控制台自己的id和随机数上写。它看起来如下:
public class Foo
{
Thread t1;
Thread t2;
Bar bar;
public Foo(Bar bar)
{
t1 = new Thread(GetRandomNumber);
t2 = new Thread(GetRandomNumber);
this.bar = bar;
}
public void Start()
{
t1.Start();
t2.Start();
}
private void GetRandomNumber()
{
Console.WriteLine("Thread {0} {1}", Thread.CurrentThread.ManagedThreadId,bar.GenerateRandomNumber());
}
}
所以主要是我:
static void Main(string[] args)
{
Bar bar1 = new Bar();
Bar bar2 = new Bar();
Foo f1 = new Foo(bar1);
Foo f2 = new Foo(bar2);
f1.Start();
f2.Start();
Console.ReadLine();
}
在控制台中,我可以得到一些想法:
Thread 11 34
Thread 12 9
Thread 13 34
Thread 14 9
我的问题是如何才能为每个帖子获取另一个数字?
答案 0 :(得分:3)
您需要使用所谓的seed
初始化随机生成器,这对于不同的线程是不同的。最简单的方法是:
Random rnd = new Random(Thread.CurrentThread.ManagedThreadId);
<强>更新强>
在代码中,您发布的简单更改一行不会有帮助
为了使它工作,你必须改变它,以便每个线程拥有它自己的Random
实例。那将是这样的:
public class Foo
{
Thread t1;
Thread t2;
public Foo(Func<Bar> getBar)
{
t1 = new Thread(()=>GetRandomNumber(getBar()));
t2 = new Thread(()=>GetRandomNumber(getBar()));
}
public void Start()
{
t1.Start();
t2.Start();
}
private void GetRandomNumber(Bar bar)
{
Console.WriteLine("Thread {0} {1}", Thread.CurrentThread.ManagedThreadId,bar.GenerateRandomNumber());
}
}
static void Main(string[] args)
{
Foo f1 = new Foo(()=>new Bar());
Foo f2 = new Foo(()=>new Bar());
f1.Start();
f2.Start();
Console.ReadLine();
}
答案 1 :(得分:0)
当您调用Random rnd = new Random();
时,随机数生成器的种子将根据系统时钟进行初始化。那时钟的分辨率并不是那么好(我不记得频率,但我相信它每秒不到100个滴答)。因此,两个线程使用系统时钟同时在Random
的实例中创建,因此两者都具有相同的种子。
种子决定了它将产生的伪随机数序列。由于两个线程都获得相同的种子,因此两者都可以产生相同的序列。
最佳解决方案是仅创建一个Random
对象的实例并将其传递给您的线程(并可能保护对它的访问,因为我不确定它是否是MT安全的。)
另一个是提供一些其他种子生成器而不是默认的种子生成器,例如将系统时间与线程id或类似网格结合起来(请注意,作为种子的托管线程id可能不够,因为托管线程ID通常倾向于挂起较低的范围,因此你的随机种子将是非常可预测的,因此根本不是随机的。)