我正在尝试使用C#中的Threads生成素数。用户必须输入要生成的线程数。运行代码时出现以下问题:
2 3 五 7 11 13 17 19 23 29 31 37 41 43 47 2 3 五 7 11 13 17 19 23 29 31 37 41 43 47
我已经完成了以下帖子。但我无法解决这些问题。我是线程概念的新手。如何解决这些问题?
Simple prime number program - Weird issue with threads C#
这是我的代码
class Program {
const int min = 2;
const int max = 100;
static List<int> primes = new List<int> ();
static void GeneratePrimes (int start, int range) {
bool isPrime = true;
int end = start + range;
for (int i = start; i <= end; i++) {
for (int j = start; j <= end; j++) {
if (i != j && i % j == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
primes.Add (i);
}
isPrime = true;
}
}
static void Main (string[] args) {
int threadCount = Convert.ToInt32 (Console.ReadLine ());
Thread[] threads = new Thread[threadCount];
int range = (max - min) / threadCount;
int start = min;
for (int i = 0; i < threadCount; i++) {
int startl = start;
threads[i] = new Thread(new ThreadStart(() => GeneratePrimes(start, range)));
startl += range;
threads[i].Start ();
}
for (int i = 0; i < threadCount; i++)
threads[i].Join();
PrintPrimes();
}
static void PrintPrimes () {
foreach (int i in primes)
Console.WriteLine (i);
}
}
更新
我按照NikolayKondratyev的回答中的建议进行了修改。但是,当我使用更多线程(&gt; 5)时,我现在在列表中有重复值
答案 0 :(得分:5)
第一个问题是线程错误start
。线程创建应该是
for (int i = 0; i < threadCount; i++) {
var startl = start;
threads[i] = new Thread(new ThreadStart(() => GeneratePrimes(startl, range)));
start += range;
threads[i].Start();
}
同样List
不是线程安全的,使用Thread-Safe Collections。
例如ConcurrentQueue
及其方法Enqueue
。
for
条件也存在问题,它们应如下所示
for (var i = start; i < end; i++)
{
for (var j = min; j < end; j++)
{
...
}
}
你可以用
来优化它for (var j = min; j < Math.Sqrt(end); j++)
另一个问题是您的范围错误,可能存在未处理的值,因为start + range
例如,对于5个线程,小于max
。因此,对于最后一个线程,我们需要添加(max - min)%threadCount
更多价值观。这是完整的代码
class Program
{
private const int min = 2;
private const int max = 100;
private static readonly ConcurrentQueue<int> primes = new ConcurrentQueue<int>();
private static void GeneratePrimes(int start, int range)
{
var isPrime = true;
var end = start + range;
for (var i = start; i < end; i++)
{
for (var j = min; j < Math.Sqrt(end); j++)
{
if (i != j && i%j == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
primes.Enqueue(i);
}
isPrime = true;
}
}
private static void Main(string[] args)
{
var threadCount = Convert.ToInt32(Console.ReadLine());
var threads = new Thread[threadCount];
var range = (max - min)/threadCount;
var start = min;
for (var i = 0; i < threadCount - 1; i++)
{
var startl = start;
threads[i] = new Thread(() => GeneratePrimes(startl, range));
start += range;
threads[i].Start();
}
threads[threadCount - 1] = new Thread(() => GeneratePrimes(start, range + (max - min)%threadCount));
threads[threadCount - 1].Start();
for (var i = 0; i < threadCount; i++)
threads[i].Join();
PrintPrimes();
}
private static void PrintPrimes()
{
foreach (var i in primes)
Console.WriteLine(i);
}
}