C军

不玩博客了!

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一、多线程I/O

1、单线程采集100个页面

    class Program
    {
        static int i = 6991275;
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            getTitle();
            sw.Stop();
            Console.WriteLine("采集100个页面完成,用时:" + sw.ElapsedMilliseconds + "毫秒");

            Console.ReadKey();
        }

        static void getTitle()
        {
            for (int j = 0; j < 100; j++)
            {
                WebClient wc = new WebClient();
                wc.BaseAddress = "http://www.juedui100.com/";
                wc.Encoding = Encoding.UTF8;
                string html = wc.DownloadString("user/" + ++i + ".html");
                Regex reg = new Regex(@"<title>(.*)</title>");
                Console.WriteLine(reg.Match(html));
            }
        }
    }

  输出:

  

2、多线程采集100个页面

    class Program
    {
        static int i = 6991275;
        static volatile int k = 1;
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 0; i < 5; i++)
            {
                ThreadPool.QueueUserWorkItem(getTitle);
            }
            while (true)
            {
                if (k == 5)
                {
                    sw.Stop();
                    break;
                }
            }
            Console.WriteLine("采集100个页面完成,用时:" + sw.ElapsedMilliseconds + "毫秒");
            Console.ReadKey();
        }

        static void getTitle(object o)
        {
            while(i < 6991375)
            {
                WebClient wc = new WebClient();
                wc.BaseAddress = "http://www.juedui100.com/";
                wc.Encoding = Encoding.UTF8;
                string html = wc.DownloadString("user/" + Interlocked.Increment(ref i) + ".html");
                Regex reg = new Regex(@"<title>(.*)</title>");
                Console.WriteLine(reg.Match(html));
            }
            k++;
        }
    }

  输出如下:

  

  单纯从执行时间来看,采集100个页面,用5个线程效率提升2倍多,当然这跟带宽也有关系啦。

  有问题,好像K++多个线程执行的时候有问题,也要Interlocked.Increment。

二、多线程计算

  今天接手了三维计算,当集合里的数量超过100个时,计算就明显变慢,三维计算是一位已离职的同事写的,尽可能的调优之后,由于算法看得还不是特别懂,只是感觉效率比较低。觉得不行,还要多线程。150个元素的集合,单线程要13秒,而启用多线程之后,可以将时间优化到5秒,速度可以提升60%。

  归根结底,这种操作慢的问题,还是算法效率不高,一时间也理解不了。要想进一步提升,后面再看懂了它的算法之后,还是把算法的效率解决才是王道,暂时先用多线程扛一扛。

            #region 多线程

            int aRound = 25;
            rCount = (int)Math.Ceiling((double)hardwares.Count / aRound);
            List<List<IngoHardwareObject>> listAll = new List<List<IngoHardwareObject>>();
            for (int i = 0; i < rCount; i++)
            {
                List<IngoHardwareObject> listA = hardwares.Skip(i * aRound).Take(aRound).ToList();
                listAll.Add(listA);
            }

            foreach (List<IngoHardwareObject> listA in listAll)
            {
                HP hp1 = new HP();
                hp1.hardwares = listA;
                hp1.planks = planks;
                ThreadPool.QueueUserWorkItem(CalCollision, hp1);
            }

            while (true)
            {
                if (aCount == rCount)
                {
                    break;
                }
            }

            #endregion

  测试时,由于集合的计算是互不相干的,唯一相关的就是汇总结果要统计到同一个哈希表,所以可以启用多线程。但写入就不能多个线程同时写入了,要Lock一下,否则数据会乱七八糟,我也猜不出会有什么后果。

  简单说来,其里面的逻辑就是,集合有150个元素,把这个List分成多个,每个25个元素,多个线程同时开始计算。

  如果不用多线程,就是算完一个,又算一个。每个集合25个元素,那就是6个线程,一有机会就算。

  为什么分成一个组25个?这个是调试出来的,我发现25个是最快的,所以设置成了25个。如果不是因为这个计算太慢,这样搞多线程,其实是得不偿失的,为啥?因为你又要切割集合,又要装载线程,又要分批汇总。只有这种单线程明显慢的计算,才能从多线程中获益!

        static void CalCollision(object OHP)
        {
            Dictionary<IngoHardwareObject, Collision> dicC = new Dictionary<IngoHardwareObject, Collision>();
            HP hp = OHP as HP;
            foreach (IngoHardwareObject ingoHard in hp.hardwares)
            {
                List<IngoPlankObject> listNearPlank = hp.planks.FindAll(o => o.MayCollision(ingoHard) && o.Key != ingoHard.Key).ToList();
                if (listNearPlank.Any())
                {
                    Collision collision = new Collision() { collisionType = CollisionType.HardwareVsPlank };
                    if (ingoHard.HardwareType == HardwareType.双头连杆)
                    {
                        List<CollisionInfo> collisionInfo = CheckCollisionMul(ingoHard, listNearPlank);
                        if (collisionInfo.Any())
                        {
                            collision.Infos.AddRange(collisionInfo);
                        }
                    }
                    else
                    {
                        for (int i = 0; i < listNearPlank.Count; i++)
                        {
                            List<CollisionInfo> collisionInfo = CheckHardwareCollisionMul(ingoHard, listNearPlank[i]);
                            if (collisionInfo.Any())
                            {
                                collision.Infos.AddRange(collisionInfo);
                            }
                        }
                    }
                    dicC[ingoHard] = collision;
                }
            }

            lock(objDic)
            {
                foreach(KeyValuePair<IngoHardwareObject, Collision> item in dicC)
                {
                    dicCollision[item.Key] = item.Value;
                }
            }

            aCount++;
        }

  由于不允许多个线程同时写入Dic,所以Lock了一下。后面等待优化。

posted on 2013-11-28 15:15  逆心  阅读(2000)  评论(0编辑  收藏  举报