当前位置: 代码迷 >> C# >> 继续一个线程的简单有关问题
  详细解决方案

继续一个线程的简单有关问题

热度:133   发布时间:2016-05-05 04:58:40.0
继续一个线程的简单问题
上个贴分结算的不太合理,这个贴纠正,也希望大家能够踊跃参与
俩个按钮一个是单线程一个是多线程
按钮1: 打印10000的数字
按钮2:建立多个线程打印10000的数字  
例如5个:
1线程 0-1999
2线程2000-3999
以此类推,然后计算时间,我发现单线程时间要远远小于多个线程,这是为什么呢,原理说细致点,还有我那个多线程等待所有子线程都结束后,在计算时间的方式对吗?
谢谢大家,效率结贴!

//这里是多线程处理问题
private void button2_Click(object sender, EventArgs e)
        {
            DateTime dtBegin = DateTime.Now;

            int batchCount = 2000;//单线程批次处理数量
            int needDealNumber = 10000;//需要处理的数量
            int threadCount = (int)Math.Ceiling(needDealNumber * 1.0 / batchCount); //启用线程数

            Thread[] thArray = new Thread[threadCount];

            for (int i = 0; i < thArray.Length; i++)
            {
                int startIndex = i * batchCount;
                int endIndex = (i + 1) * batchCount;
                ThreadStart ts = new ThreadStart(delegate
                {
                    Show(startIndex, endIndex);
                });
                Thread tt = new Thread(ts);
                tt.Name = "线程" + (i + 1);
                tt.IsBackground = true;
                thArray[i] = tt;
                tt.Start();
            }
            foreach (Thread t in thArray)
            {
                t.Join();
            }
            TimeSpan tspan = DateTime.Now - dtBegin;
            MessageBox.Show(tspan.TotalSeconds.ToString());
        }
private void Show(int startIndex, int endIndex)
        {
            for (int i = startIndex; i < endIndex; i++)
            {
                Console.WriteLine(Thread.CurrentThread.Name + "处理了:" + i);
            }
        }
//单线程处理
private void button1_Click(object sender, EventArgs e)
        {
            Show();
        }
private void Show()
        {
            DateTime dtBegin = DateTime.Now;
            for (int i = 0; i < 10000; i++)
            {
                Console.WriteLine(i);
            }
            TimeSpan ts = DateTime.Now - dtBegin;
            MessageBox.Show(ts.TotalSeconds.ToString());
        }


------解决思路----------------------
帮你顶一下,我也纠结多线程的问题呢
------解决思路----------------------

原因很简单,多线程一般用于执行”耗时”的任务;

1-10000串行打印可以说是瞬间的事,你开了N个线程,线程的创建,切换,销毁的开销反而没串行快;

如果是有10000个耗时的任务,比方说每个任务N秒钟,这个时候才考虑用多线程;

另外这种任务完全可以用TPL代替。


------解决思路----------------------

DateTime dtBegin = DateTime.Now;
 
            int batchCount = 2000;//单线程批次处理数量
            int needDealNumber = 10000;//需要处理的数量
            int threadCount = (int)Math.Ceiling(needDealNumber * 1.0 / batchCount); //启用线程数
 
            Thread[] thArray = new Thread[threadCount];
 
            for (int i = 0; i < thArray.Length; i++)
            {
                int startIndex = i * batchCount;
                int endIndex = (i + 1) * batchCount;
                ThreadStart ts = new ThreadStart(delegate
                {
                    Show(startIndex, endIndex);
                });
                Thread tt = new Thread(ts);
                tt.Name = "线程" + (i + 1);
                tt.IsBackground = true;
                thArray[i] = tt;
                tt.Start();
            }
            foreach (Thread t in thArray)
            {
                t.Join(); 这里的JOIN是阻塞,要等线程执行完才继续,这很耗时的
            }


光执行这个就耗了不少时间了,还不算线程里面的
还有如果用多线程执行这种简单的计算,他的速度真没多线程快。
线程的效率是看CPU核心,如果单核的,你用线程返而更慢


------解决思路----------------------
要发挥多线程的优势,也是有条件的,一是有多个CPU,二是所干的事情不繁重,有偷懒的情况.
就楼主的线程要干的事,本身太简单了没有偷懒的可能,而且干的批量很小,使切换线程的开销比重加大了.
------解决思路----------------------
一个线程运行时可以跑20ms,跑10000个够了,根本就不用线程切换。

线程切换,需要将上一个线程的环境保持起来,然后再加载这个线程,然后再才开始执行代码。


在大量工作都需要进行的时候,业务复杂,业务需等待其他业务完成时,多线程可以提供效率。  但如果只是简单的工作,开辟过多线程是浪费资源。

最后,即便是打印100000000个,在单核CPU下,依旧是单线程快。工作业务太简单了。
------解决思路----------------------
多线程的优势在于不相关任务的并发处理,如果任务可以拆分成完全不相关的子任务,那么理论上n个线程就是n倍的效率。但是如果任务有关联(比如运行顺序或者共享资源,还有一些底层软件和硬件上的潜在关联),都会影响并发性能。

你这里主要是因为任务里面使用了Console.WriteLine,它会导致线程需要同步,时间浪费在等待其它线程的WriteLine完成上。

任务分为计算密集型和I/O密集型。计算密集型就是大量占用CPU时间(比如视频编码),这种任务最多使用CPU核心数量的线程就够了,再多CPU也不可能并发处理。I/O密集型是频繁对网络、磁盘等等读写(比如web服务器),这种场景线程不占用多少CPU时间,几乎都是处于等待I/O的状态,更应该考虑使用异步I/O调用,而不是使用大量线程。

如果希望深入了解多线程,有一系列很好的文章:http://www.albahari.com/threading/,国内也有翻译自它的资源。

计时这个上次说了,用Stopwatch更精确。DateTime.Now除了不够精确外还有个问题,就是依赖系统时间,如果计时过程中系统时间被改变(人为或者系统自动同步),计时就不准了。Stopwatch最简单的用法:
Stopwatch w = Stopwatch.StartNew();
// 执行任务
w.Stop();
// 取结果 w.ElapsedMilliseconds 或者 w.Elapsed
  相关解决方案