Prime数字生成器使用线程

时间:2015-12-23 05:20:45

标签: c# multithreading

我正在尝试使用C#中的Threads生成素数。用户必须输入要生成的线程数。运行代码时出现以下问题:

  1. 如果我尝试使用多个线程,有时候索引超出范围异常。如果我再试一次,它就可以了。
  2. 每个线程都在计算相同的值。例如,如果我输入两个线程来生成2到100之间的素数(包括两者),我得到以下输出。
  3. 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)时,我现在在列表中有重复值

1 个答案:

答案 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);
    }
}