这几天晚上群里一朋友有偿叫我把他的程序弄稳定,因为是现场管理项目,需要做到无人职守,所以即使是客户端,也不能经常down机,因为之前对他的程序有过一个晚上的实地查看,基本流程已经有个大概的了解,我就接下来了。

刚开始的时候, 程序运行不到一个上午,内存暴涨,有时几个小时就挂了,这个那天晚上发现了,找了半天发现一处加载图片的TMemoryStream没有释放。

没想到接下来还有很多的坑需要填。

一个个解决吧,看看有多少坑!

第一天:开始他跟我说他的连接数据库老是超出数量,会导致程序不能处理任务,当天晚上就用diocp3中的BaseQueue做了个轻便的ADO连接池,因为baseQueue做了大量的测试,所以这个ado连接池经过简单的测试就算OK了,接下来就大量的苦力工作了。

第二天:说连接池换上后,连接问题没有了,可是线程池不能处理任务了。他之前使用的一个叫uThreadPool单元,代码好复杂。我推荐他使用QWokers,因为qwokers我一直在使用,很稳定了,任务的投递也很简单,后来一想,他是D7,没办法用这么好的类库,没办法,只好iocpTask上了。iocpTask diocp3中的一个任务投递的库, 是个类似qworker的库,不过只有任务投递和执行的功能,比起qworker来说太简单了,不过用iocpEngine稳定性应该也是不错的了。换上后,我接着对iocpTask做了写修改,加强了调试信息,能够很方便的看到工作线程的当前状态,和任务执行的状态。

因为他说线程池有问题,我估计肯定是卡在哪个任务了,到时候卡死的时候一看就明白了。

下面是iocpTask输出的状态信息,

post counter:10000001
response counter:10000001
error counter:0active : True, worker count: 5
----------------------- woker 1 --------------------
thread id: 9664, response count: 1719388
busying:False, waiting:True, reserved:True
request state info:
runInMainThread: False, done: True, time(ms): 0
----------------------- woker 2 --------------------
thread id: 6680, response count: 2010817
busying:False, waiting:True, reserved:True
request state info:
runInMainThread: False, done: True, time(ms): 0
----------------------- woker 3 --------------------
thread id: 4956, response count: 1965637
busying:False, waiting:True, reserved:False
request state info:
runInMainThread: False, done: True, time(ms): 0
----------------------- woker 4 --------------------
thread id: 8304, response count: 2641407
busying:False, waiting:True, reserved:False
request state info:
runInMainThread: False, done: True, time(ms): 0
----------------------- woker 5 --------------------
thread id: 9528, response count: 1662752
busying:False, waiting:True, reserved:False
request state info:
runInMainThread: False, done: True, time(ms): 0

因为是gitHub上面的项目所以我用了E文注释和E文信息,中式英文,都懂的,稍微解释下,

post counter:10000001          //代表投递的任务数

response counter:10000001  //响应数

error counter:0                         //投递失败数量

下面是工作线程的一些信息,有线程ID, 响应处理的任务数量,

下面的状态比较关键

busying 的true的话就是代表正在执行任务,wating是在等待状态, reserved是代表常驻工作线程

如果busying为true,会跟着出现当前正在执行的任务信息,如果任务都在执行这样线程池达到最多的线程数,就不能处理新的任务了。导致了他程序发生的情况。这样可以根据任务的信息找到对应的过程,去缩小范围查询问题。

request state info: 如果任务有备注信息,会显示在这里

runInMainThread:是否在主线程执行的任务,done:任务是否完成, time(ms): 是任务耗用的时间。

有了iocpTask这个坑很快找到了。

发现原来临界用了很多,导致了任务死锁…,

明天要接着填临界的坑了。

第三天:他的程序临界使用泛滥,当前进入不了临界,导致任务挂起,但是并不是当前临界的问题,是因为有其他任务进入临界没有退出。所以要找出前面的临界,把临界类改造了下。

可以看到临界的当前信息,我把iocpLocker也进行了相应的升级

function TIocpLocker.getDebugINfo: String;
beginResult := Format('%s: busycount:%d, try:%s, enter:%s', [self.FName, GetEnterCount, FTryEnterInfo, FEnterInfo]);
end;

可以获取临界的名称,进入尝试进入临界的线程个数,尝试进入临界的信息和已经进入临界的信息。

有了这个数据就可以看到死锁的临界已经进入的临界信息就是代表造成死锁的元凶了。

第四天:因为线程里面对UI的访问过多,可以用iocpTask在线程中对 UI的访问部分,通过投递任务的方式投递到主线程中完成工作,这也是个苦力。

认真的对他的程序做了改进,并讲解了多线程编程需要注意的地方<后面会总结>,虽然后面程序还有写bug。他还是很爽快的把钱给付了,说即使程序还有问题也值了,通过这次填坑交流知道要注意很多地方。这算是对我这次工作的最大肯定吧。

总结:

通过对这次填坑和以往DIOCP群里面一些朋友的问题和做法,我列出下多线程程序编写需要遵循的几点,希望对大家有所帮助:

1.子线程千万不要访问主线程的UI,(memo,Label),我发现这样做的程序员很多,在diocp中经常会用到onConnected/OnDisconnected事件中直接操作主窗体的Memo。导致程序无法正常退出,或者出现卡死主界面的情况,原因我想可以归纳到访问冲突上面,用临界也不能解决问题。很多组件都是靠windows消息驱动,他才不会使用零件去处理消息,所以临界也没办法。你只有老老实实的投递到主线程去完成这部分工作,qworker和iocpTask都可以很好的完成这项工作。

2.线程之间访问共享资源需要用临界,千万不要多个线程同时去处理同一个变量,或者列表,否则就等着出现各种问题吧。

3.数据库连接尽量用连接池去完成,这样既可以减少连接,也可以很好的避免多个线程对同一个连接的使用。

当然还有很多细小的问题,需要自己去注意了。

转载于:https://www.cnblogs.com/DKSoft/p/3938487.html

多线程程序的填坑笔记和多线程编程应该遵循的规则相关推荐

  1. [react-native]react-native填坑笔记

    填坑笔记 开始入坑RN,从最开始的学起难免有不少乱七八糟的问题,记录在这里. 1. 8081端口占用问题 按照官网教程搭建开发环境并按照下面代码运行时候有报错,显示8081端口的问题 react-na ...

  2. 即将上线的Hive服务器面临的一系列填坑笔记

    即将上线的Spark服务器面临的一系列填坑笔记 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.18/10/19 16:36:31 WARN metastore.ObjectSt ...

  3. 即将上线的flume服务器面临的一系列填坑笔记

      即将上线的flume服务器面临的一系列填坑笔记 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.flume缺少依赖包导致启动失败! 报错信息如下: 2018-10-17 ...

  4. unity代码更换ui图片_Unity3d 低分辨率UI素材换高分辨率素材填坑笔记

    迷糊 RectTransform PosX.PosY.Left .Right . Top .Bottom 以及 AchorMax/AnchorMin 的,开卷有益哟~ 背景 笔者开发的(PC)APP ...

  5. 填坑笔记-linux下安装cadence

    在Linux下有很多spice的仿真软件, 我之前用过ngspice, 也还在折腾. cadence也是一个比较优秀的软件,主要是有Linux版本支持,我于是又来了. windows之所以那么好用,给 ...

  6. win10安装TensorFlow填坑笔记

    研究了一段人工智能的基础理论以后,终于决定安装一套TensorFlow来练练手.郑重其事的将一台电脑重装了win10,网上找了几个安装攻略,照着安装TensorFlow For windows.结果就 ...

  7. H5填坑笔记--持续更新

    最近一直在做移动端的页面,发现很多的坑,这里做一下总结,填填坑-- css常见的问题(一) 一.iOS键盘首字母自动大写 IOS的机子,默认英文输入法状态下,首字母是自动大写的,有时候挺烦人的. 在i ...

  8. 消息长度_填坑笔记:RocketMQ消息订阅失败问题?

    前语:不要为了读文章而读文章,一定要带着问题来读文章,勤思考. 作者:kinnylee   来源:http://1t.click/g26 # 背景介绍 项目组使用阿里RocketMQ,对同一个消费组设 ...

  9. nginx php 跨域访问权限,nginx + php 实现跨域请求填坑笔记

    最近自己构建了一个轻量级的 MVC 框架,现在将该MVC用于生产环境的项目中,目前因为项目中有跨域的请求,所以需要做一些CORS授权,但在实际使用出现了一些问题,目前已解决,故做下记录. 服务器:ce ...

  10. 公网访问阿里云数据库MongoDB——填坑笔记

    业务情景 两台服务器,一台阿里云ECS云服务器(专用网络),另一台是阿里云数据库MongoDB,处于安全考虑MongoDB是不运行外网连接的,那接下来就看怎么实现公网访问. 看到上面红色的网络类型描述 ...

最新文章

  1. CCS编译添加链接库文件与头文件的方法
  2. 影响u盘传输速度和使用寿命的几大因素
  3. 汇编语言---计算有符号数算式的值
  4. 基于块的linux驱动程序,基于块的Linux驱动程序 块设备驱动 centos内核编译过程 操作系统课程设计...
  5. python叮当猫代码_详细介绍一个利用html+css实现叮当猫的实例代码
  6. 我们常说的算法时间复杂度和空间复杂度到底是什么?
  7. 【差分算法入门】例题讲解(代码逐句分析)
  8. ES6 Set结构和Map结构(上)
  9. as400 编程语言c,AS400_RPG入门
  10. Dubbo源码解析-Dubbo协议解析
  11. LYNC 2010 中文测试版已经可以下载
  12. 【代码重构】拒绝继承的遗赠(Refused Bequest)--如何处理子类无需使用到父类中的某些方法和变量的情况?
  13. Nine-Patch点九切图法
  14. 7_22_html_美食网设计
  15. vue编程式导航跳转到当前路由多次执行抛出NavigationDuplicated: Avoided redundant navigation to current location:
  16. NASA开始调试校准韦伯望远镜18面金色镜子,需三个月
  17. java vm art 2.1.0_ART Runtime 创建(二)--启动参数
  18. 面对肺炎疫情小贴士-IT奶爸带娃记
  19. 乔布斯经典语录:洗尽铅华的感悟
  20. 小学生计算机清除键是mc,我的世界一键清除指令 | 手游网游页游攻略大全

热门文章

  1. 数据采集及预处理——针对“数据”“采集”“预处理”的理解与解析
  2. Effective java 读书笔记
  3. 边际递减,边际成本,边际收益,边际效益
  4. 【gitee】解决gitee本地提交但是无法显示贡献度(绿点)的问题
  5. Android 读取bin文件方法
  6. win7系统配置时间服务器,与Internet时间服务器同步 设Win7精确时间
  7. golang反射的类型Type与种类Kind使用
  8. Chrome浏览器安装vue插件(附插件下载地址)
  9. jsjq面试笔记(上)
  10. springboot 定时器使用方法之并行