一、多线程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了一下。后面等待优化。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2012-11-28 CSS常用属性