zoukankan      html  css  js  c++  java
  • 线程系列02,多个线程同时处理一个耗时较长的任务以节省时间

    当面对一个耗时较长的任务时,我们可以把这个任务切分成多个部分,然后同时交给多个线程处理。

     

    □ 统计字节数组一个比较耗时的方式

    以下来统计一个字节数组的大小。

        class Program
    
        {
    
            static byte[] values = new byte[500000000];
    
            static void Main(string[] args)
    
            {
    
                GenerateByteArray();
    
                Console.WriteLine("正在统计字节数");
    
                Stopwatch watch = new Stopwatch();
    
                watch.Start();
    
                long total = 0;
    
                for (int i = 0; i < values.Length; i++)
    
                {
    
                    total += values[i];
    
                }
    
                watch.Stop();
    
                Console.WriteLine("统计结果为:" + total);
    
                Console.WriteLine("计算时间为:" + watch.Elapsed);
    
            }
    
            static void GenerateByteArray()
    
            {
    
                var r = new Random(987);
    
                for (int i = 0; i < values.Length; i++)
    
                {
    
                    values[i] = (byte)r.Next(10);
    
                }
    
            }
    
        }
    

    3

    如果把统计工作同时交给多个线程,是否可以把统计时间省下来呢?

     

    □ 同时使用多个线程

    现在要对"统计字节数组大小"这个任务进行均分、切分。首先面临的问题是:按什么标准均分?
    --这个完全是靠个人喜好,可以让2个线程,3个线程......来处理。在这里,就根据CPU的数量来均分,因为CPU的数量可以通过Environment.ProcessorCount获得。

     

    面临的第二问题是:均分什么?
    --比如有4个CPU
    --那可以把任务分成4个线程同时处理
    --把字节数组的长度均分,比如字节数组的长度是1000,均分成4段,每段长度为250
    --把字节数组的大小分成4个放一个数组里,即[sum1, sum2, sum3, sum4],所有的元素加起来就是字节数组的总大小

        class Program
    
        {
    
            static byte[] values = new byte[500000000];
    
            //分段统计的大小放该数组,比如分成4等份,[10000,10005,10008,10009]
    
            private static long[] partialSum; 
    
            //把values数组长度均等分,比如长度1000,分成4粉,那partialSize就是250
    
            private static int partialSize;
    
            static void Main(string[] args)
    
            {
    
                //根据CPU的数量确定数组的长度
    
                partialSum = new long[Environment.ProcessorCount];
    
                //根据CPU的数量确定数组长度均等分
    
                partialSize = values.Length/Environment.ProcessorCount;
    
                GenerateByteArray();
    
                Console.WriteLine("正在统计字节数");
    
                Stopwatch watch = new Stopwatch();
    
                watch.Start();
    
                long total = 0;
    
                for (int i = 0; i < values.Length; i++)
    
                {
    
                    total += values[i];
    
                }
    
                watch.Stop();
    
                Console.WriteLine("统计结果为:" + total);
    
                Console.WriteLine("计算时间为:" + watch.Elapsed);
    
                Console.WriteLine();
    
                watch.Reset();
    
                watch.Start();
    
                Thread[] threads = new Thread[Environment.ProcessorCount];
    
                for (int i = 0; i < Environment.ProcessorCount; i++)
    
                {
    
                    threads[i] = new Thread(SumPartial);
    
                    threads[i].Start(i);
    
                }
    
                //保证一个线程结束再执行下一个线程
    
                for (int i = 0; i < Environment.ProcessorCount; i++)
    
                {
    
                    threads[i].Join();
    
                }
    
                //统计总大小
    
                long total2 = 0;
    
                for (int i = 0; i < Environment.ProcessorCount; i++)
    
                {
    
                    total2 += partialSum[i];
    
                }
    
                watch.Stop();
    
                Console.WriteLine("使用分段线程统计的大小:" + total2);
    
                Console.WriteLine("计算时间为:" + watch.Elapsed);
    
            }
    
            /// <summary>
    
            /// 分段统计字节数组的大小
    
            /// </summary>
    
            /// <param name="partialNumber">比如有4个CPU,partialNumber可能的值是0, 1, 2, 3</param>
    
            static void SumPartial(object partialNumber)
    
            {
    
                long sum = 0;
    
                int partialNumberAsInt = (int)partialNumber;
    
                int baseIndex = partialNumberAsInt * partialSize;
    
                for (int i = baseIndex; i < baseIndex + partialSize; i++)
    
                {
    
                    sum += values[i];
    
                }
    
                partialSum[partialNumberAsInt] = sum;
    
            }
    
            /// <summary>
    
            /// 创建字节数组
    
            /// </summary>
    
            static void GenerateByteArray()
    
            {
    
                var r = new Random(987);
    
                for (int i = 0; i < values.Length; i++)
    
                {
    
                    values[i] = (byte)r.Next(10);
    
                }
    
            }
    
        }
    

    以上,统计字节数组大小的方式倒不是最重要的,线程部分才是重点:
    ○ 有几个CPU,就有几个线程
    ○ 线程的实例方法Start可以传递object类型的参数
    ○ 线程的实例方法Join,用来保证执行完上一个线程再执行下一个线程

    5
    在这里,使用多线程同时处理一个任务,效率差不多提高了2.6倍!

     

    总结:
    ○ 对于一个比较耗时的任务可以同时交给多个线程处理
    ○ 线程的实例方法Join保证执行完上一个线程再执行下一个线程

     

     

    线程系列包括:

    线程系列01,前台线程,后台线程,线程同步

    线程系列02,多个线程同时处理一个耗时较长的任务以节省时间

    线程系列03,多线程共享数据,多线程不共享数据

    线程系列04,传递数据给线程,线程命名,线程异常处理,线程池

    线程系列05,手动结束线程

    线程系列06,通过CLR代码查看线程池及其线程

    线程系列07,使用lock语句块或Interlocked类型方法保证自增变量的数据同步

    线程系列08,实现线程锁的各种方式,使用lock,Montor,Mutex,Semaphore以及线程死锁

    线程系列09,线程的等待、通知,以及手动控制线程数量

    线程系列10,无需显式调用线程的情形

  • 相关阅读:
    c#接口和抽象类的区别(转)
    Dephi阿拉伯数字转换成英文和中文大写
    Code Rush Express Template 制作
    SQL中对学习成绩自动排名次
    Resharper上手指南
    如何實現域控制中部分用戶可以寫Programme files目錄的權限?
    阿拉伯数字转换英文数字表示算法解析及其实现
    BOM 算法
    OGRE1.7.1.1vs2008安装
    近一个月工作小总结
  • 原文地址:https://www.cnblogs.com/darrenji/p/3980252.html
Copyright © 2011-2022 走看看