现在有这样一个问题,存在一个集合,集合中的元素很多,为了提高处理速度,于是使用下面的代码(多线程)来处理集合,思路是这样:使用M个多线程,将集合分成M页,每个线程处理该集合中第i页的数据,但是不知道是什么原因,不论我将M设为多少,整个处理时间都没有得到明显的改善,请高手指点
public class Program
    {
        public static void Main()
        {
            DateTime dt1 = DateTime.Now;
            List<Num> list1 = new List<Num>();
            for (int i = 0; i < 200000; i++)
            {
                list1.Add(new Num(100));
            }            int M = 5;
            Thread[] threads = new Thread[M];
            for (int i = 0; i < M; i++)
            {
                threads[i] = new Thread(new ParameterizedThreadStart(UpdateNumList));
                threads[i].Start(new NumDecorate(list1, list1.Count / M, i));
                threads[i].Join();
            }
            DateTime dt2 = DateTime.Now;
            Console.WriteLine("{0}--{1}", dt1.ToLongTimeString(), dt2.ToLongTimeString());
            Console.Read();
        }        public static void UpdateNumList(Object p)
        {
            NumDecorate nd = (NumDecorate)p;
            for (int i = 0; i < nd.PageSize; i++)
            {
                nd.NumList[nd.PageIndex * nd.PageSize + i].Value += nd.PageIndex * nd.PageSize + i;
                Console.WriteLine("{0}--{1}", nd.PageIndex * nd.PageSize + i, nd.NumList[nd.PageIndex * nd.PageSize + i].Value);
                //Thread.Sleep(300);
            }
        }
    }    public class Num
    {
        public Num(int m)
        {
            this.Value = m;
        }        public int Value { get; set; }
    }    public class NumDecorate
    {
        public List<Num> NumList { get; set; }
        public int PageSize { get; set; }
        public int PageIndex { get; set; }        public NumDecorate(List<Num> numList, int pageSize, int pageIndex)
        {
            this.NumList = numList;
            this.PageIndex = pageIndex;
            this.PageSize = pageSize;
        }
    }

解决方案 »

  1.   

    你认为线程就会缩短时间吗,那你大错特错了,而且可能还延长了你的时间,因为cpu必须分配时间,在各个线程中切换当你的cpu的数量大于线程数的时候,你才会真正体会到线程的效率
      

  2.   

    threads[i].Join(); <--- 这会等这个线程运行结束!去掉它如果你需要最后同步所有线程,可以修改成下面:for (int i = 0; i < M; i++)
    {
        threads[i] = new Thread(new ParameterizedThreadStart(UpdateNumList));
        threads[i].Start(new NumDecorate(list1, list1.Count / M, i));
        //threads[i].Join();
    }
    for (int i = 0; i < M; i++)
    {
        threads[i].Join();
    }
    另外同意ls的观点,不是线程越多越快哈。
      

  3.   

    join的位置没有影响。另外,如果我想以最快的速度处理完这个集合,应该采用什么方式?
      

  4.   

    还没影响?threads[i].Start(new NumDecorate(list1, list1.Count / M, i));
    threads[i].Join();这样的话,当前线程没结束,下一个线程不会启动。
    这和同步处理是一样的。
      

  5.   

    如果楼主是要提高处理速度,采用的应该是并行计算(多CPU同时处理)多线程运行在同一个处理器上,只是各个线程之间轮流运算,并不会提高你的运算速度。另外,多线程的目的是当应用程序需要运行一个很大的进程,同时要保证其它的UI处于激活和可用状态时,才产生多线程。而且多线程线程数不是越多越好,每开一个线程,系统都要为其分配一块内存区域,并产生一定的处理器开销。线程数量过多可能导致性能降低。另外,楼主的代码中:
    for (int i = 0; i < M; i++)
                {
                    threads[i] = new Thread(new ParameterizedThreadStart(UpdateNumList));
                    threads[i].Start(new NumDecorate(list1, list1.Count / M, i));
                    threads[i].Join();
                }
    使用Join方法,建议楼主查看下Join方法的用法,你在这里Join,则各个线程是依次进行的,threads[1]处理完后,才会创建threads[2],依次进行下去。也就是说楼主的运算没有实现多线程的机制,而且比没有使用多线程处理速度更慢了
      

  6.   

    你现在的线程里都是 Console.WriteLine 能比出效果么??把你的 Thread.Sleep(300); 打开再比较下!
      

  7.   

    我是希望当前线程也就是主线程会在所有子线程结束后运行,所以加了Join方法,按照7l说的将Join移出去了,但是也没有变化,就像你说的那样我的多线程和单线程没有区别。
      

  8.   

    线程的运行时每一段时间只有一个线程执行操作,在此使用线程只是将运算进行了分割,并没有减少运行时间如果你要减少运行时间,应该使用并行计算
    for (int i = 0; i < M; i++)
      {
      threads[i] = new Thread(new ParameterizedThreadStart(UpdateNumList));
      threads[i].Start(new NumDecorate(list1, list1.Count / M, i));
      threads[i].Join();
      }
    修改为
      System.Threading.Tasks.Parallel.For(0, M, i =>
                {
                    UpdateNumList(new NumDecorate(list1, list1.Count / M, i));
                });这样对你的数据量来说可能提高只有几个毫秒,但是如果你将数量改为2000000,你可以看到很大的提升
      

  9.   

    完整代码如下:using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;namespace ThreadPoolExample
    {
        public class Program
        {
            public static void Main()
            {
                DateTime dt1 = DateTime.Now;
                List<Num> list1 = new List<Num>();
                //这里修改为了2000000
                for (int i = 0; i < 2000000; i++)
                {
                    list1.Add(new Num(100));
                }
                int M = 5;            System.Threading.Tasks.Parallel.For(0, M, i =>
                {
                    UpdateNumList(new NumDecorate(list1, list1.Count / M, i));
                });            DateTime dt2 = DateTime.Now;
                Console.WriteLine("总共运行{0}毫秒", (dt2 - dt1).TotalMilliseconds);
                Console.Read();
            }        public static void UpdateNumList(Object p)
            {
                NumDecorate nd = (NumDecorate)p;
                for (int i = 0; i < nd.PageSize; i++)
                {
                    nd.NumList[nd.PageIndex * nd.PageSize + i].Value += nd.PageIndex * nd.PageSize + i;
                }
            }
        }    public class Num
        {
            public Num(int m)
            {
                this.Value = m;
            }        public int Value { get; set; }
        }    public class NumDecorate
        {
            public List<Num> NumList { get; set; }
            public int PageSize { get; set; }
            public int PageIndex { get; set; }        public NumDecorate(List<Num> numList, int pageSize, int pageIndex)
            {
                this.NumList = numList;
                this.PageIndex = pageIndex;
                this.PageSize = pageSize;
            }
        }}
    你可以试下和之前的运算速度比较(代码中我修改了数据量的大小),因为对小数据量进行并行处理没有实际意义
      

  10.   

    sorry,忘了说了,这个需要4.0框架
      

  11.   

    很感谢你的回答,但是经过测试运行后,我发现,在我的代码中如果处理过程里面只是修改值而不输出,则整个运行过程是192ms,而你给我的代码运行耗时是3200ms。如果在你的代码中如果增加输出,则整个程序似乎出现了死循环。我想可能是这段代码中的i没有赋值吧?System.Threading.Tasks.Parallel.For(0, M, i =>
                {
                    UpdateNumList(new NumDecorate(list1, list1.Count / M, i));
                });