为什么80%的码农都做不了架构师?>>>   

一 缘由:
    最近因工作问题,需要实现一个简单的线程池,满足一下要求,
  • 可伸缩,即一旦发现线程不够用,则可以动态增加线程。(至于缩减线程,这个可能难度比较大,暂时不考虑)。
  • 支持超时任务。比如提交一个Task,可以设置5秒后执行,并且可以设置执行一次,还是每隔5秒执行。
基本上就是这两个要求。下面讨论下实现上的问题。
 
二 Windows平台
1 Windows平台实现一个线程池(不使用完成端口),我最初的想法是:
  • 创建比如20个线程,然后这20个线程都WaitForXXXObject,在一个Event上。
  • 添加任务的时候,触发这个Event,为了避免惊群现象(例如只有1个任务的时候,20个线程全起来抢任务,结果其他19个线程白起来了。这样导致系统效率会显著下降。),CreateEvent的时候可以设置下,保证只有一个在等待的线程会启动。
问题:
  • 不太好实现超时任务,这20个线程,该哪一个去做超时检测呢?虽然Wait函数提供了超时机制,但总不可能这20个都去做超时检测吧?
  • 解决办法是,可能需要单独一个线程去定时检查,然后把到期的任务加入到任务队列头,然后触发Event,这样其他线程就能顺利得到任务了。
  • 另外一种方式是这20个线程中有一个做超时检查,然后执行最先到期的任务。这样的问题就是如果该线程执行的任务要是时间过长的话,将导致其他超时任务没法执行。
  • 综合考虑的话,还是用一个单独的线程去检查比较好。
2 Windows平台上使用完成端口
  • 使用完成端口就简单了,线程池中的线程个数将是CPU个数的2倍(这个是推荐值,应该也是绝大多数人的选择了)。
  • Wait的时候,当有事情发生时,内核会自动调度一个线程去执行。而且接连的任务会倾向于使用同一个线程来执行。这样可以减少线程切换的时间。所以,惊群效应由内核保证不会发生了。
  • 解决超时任务的检查,这个也没有更好的办法。只能采取和上面一样的方法了。
三 Linux平台
1 Linux平台实现线程池,基本思路和Windows一样,但是由于Linux提供的线程同步原语(POSIX)不如Windows好用,导致有一些特殊的地方需要注意:
  • 在Windows上,线程间通知无外乎就是使用Event,在Linux上,使用POSIX的condition+mutex,也能完成同样的操作,但是这种方式在linux中用得相对较少,而是大量使用pipe,创建两个fd。当线程1想唤醒线程2的时候,就可以往writeFD中写数据,这样线程2阻塞在readFD中就能返回。我之前及其没搞明白为何要使用pipe,后来突然想明白了。因为Linux上阻塞的方法就是用select,poll和epoll,其中等待的都是FD,那么采用FD这种方式,能够统一调用方法。(因为POSIX缺乏WaitForMultiObject导致,网上有一个Linux下Wait/CreateEvent的系列实现,很难下载到。呵呵)
  • 但是,现在有20个线程,总不可能创建20个pipe吧?即使有20个pipe,那么我要唤醒哪个线程,就得单独往那个线程的writeFD写数据。这明显不是一个好办法。只能使用condition+mutex了。为了避免惊群,操作cond的时候,只能使用Signal,而非Broadcast
  • 超时任务的处理,那么也只能和Windows一样的方法了
四 一个实际的线程池设计
  • 对用户来说,线程池处理的是任务。所以给线程池添加的应该是任务。那么任务有高,中,低三个优先级。另外,有些任务是需要一直占有线程的,所以还区分persist和非persist两种。设计的时候,分别有高中低三个优先级队列。线程池在挑选任务的时候,先处理高,然后是中低优先级的任务。
  • 当线程池中的线程个数小于任务个数的时候,线程池应该自动增加池中的线程。这个就是自动扩展。当线程池中的线程检测到自己长时间没有工作,并且池中线程数量超过最大设置的数量时候,那么线程应该自动退出。按这种方式就可以实现一个比较好的自动缩减。这样的话,每个线程都需要有一个超时检测,看看自己是不是多余了。
  • 对于定/超时任务,需要给线程池增加一个高优先级,persist的job。这个job自带一个定时任务队列。添加定时任务,其实就是给这个队列添加成员。然后唤醒该线程。这个线程从其中选择一个任务,然后再提交给线程池。(其实就是我们在Windows上的方案)
 
 
 

转载于:https://my.oschina.net/innost/blog/36811

随笔之如何实现一个线程池相关推荐

  1. 程序随笔——C++实现的一个线程池

    1.线程池简介 我们知道在线程池是一种多线程处理形式,处理过程中我们将相应的任务提交给线程池,线程池会分配对应的工作线程执行任务或存放在任务队列中,等待执行. 面向对象编程中,创建和销毁对象是需要消耗 ...

  2. java 手编线程池_死磕 java线程系列之自己动手写一个线程池

    欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. (手机横屏看源码更方便) 问题 (1)自己动手写一个线程池需要考虑哪些因素? (2)自己动手写 ...

  3. 一个线程池中的线程异常了,那么线程池会怎么处理这个线程?

    一个线程池中的线程异常了,那么线程池会怎么处理这个线程? 参考文章: (1)一个线程池中的线程异常了,那么线程池会怎么处理这个线程? (2)https://www.cnblogs.com/fangua ...

  4. 工作中如何使用线程池的?自己如何定义一个线程池?

    工作中如何使用线程池的?自己如何定义一个线程池? import java.util.concurrent.*;public class MyThreadPoolDemo {public static ...

  5. 设置iis网页服务器cpu占比,为什么iis的一个线程池占了100%cpu

    为什么iis的一个线程池占了快100%cpu, 这个站点是跑asp.net web api的,大多是数据库的操作. 当回收这个线程池后几分钟,cpu使用率就降下来了. 可是隔一天半天的再去服务器看,c ...

  6. 一个有趣的问题 : 如何设计一个线程池

    理解Java并发工具包线程池的设计 深度解读 java 线程池设计思想及源码实现 分布式锁unlock 问题产生原因分析: Step 1 :线程A先上同一个锁(Key)(20秒), 然后执行耗时业务, ...

  7. 【重难点】【JUC 05】线程池核心设计与实现、线程池使用了什么设计模式、要你设计的话,如何实现一个线程池

    [重难点][JUC 05]线程池核心设计与实现.线程池使用了什么设计模式.要你设计的话,如何实现一个线程池 文章目录 [重难点][JUC 05]线程池核心设计与实现.线程池使用了什么设计模式.要你设计 ...

  8. 面试官:如何评估一个线程池需要设置多少个线程

    作者 | 丁威       责编 | 欧阳姝黎 见字如面,我是威哥,一个从普通二本院校毕业,从未曾接触分布式.微服务.高并发到通过技术分享实现职场蜕变,成长为 RocketMQ 社区优秀布道师.大厂资 ...

  9. 如何实现一个“线程池”

    线程池里面包含了许多线程,可以供我们去使用,而避免了频繁的创建线程以及销毁线程,主要目的就是为了提高开发效率.那么我们如何实现一个自己的"线程池"呢 首先我们来看一下线程池的组成部 ...

最新文章

  1. 技术专题讨论:JPA vs MyBatis ?您如何选择?(有奖活动)
  2. Perl中的单行凝视和多行凝视
  3. python判断一个或者多个字符串,是否出现在一段话中
  4. Numpy中的堆叠(stack)操作
  5. JAVA连接数据库ij_Derby 客户端 ij使用
  6. C++/OpenGL:图像指针操作
  7. 监控ajax上传进度
  8. php pathseparator,在PHP拥有与命名空间和通过set_include_path()的一个问题
  9. PingInfoView,中文,以及ping包+描述的使用。
  10. duilib开发(六):基本控件介绍
  11. 吉客云与金蝶云星空集成方案(吉客云主管库存)
  12. Error: Getter not found: 'suspending'. case AppLifecycleState.suspending
  13. pomodoro源码
  14. java 自动点击网页_JS脚本实现网页自动秒杀点击
  15. CentOS中 DNF 和 Yum 的区别
  16. 关于Qt高分屏缩放几个知识点
  17. 联合体(union)的使用方法及其本质
  18. Brave浏览器或许是你打开元宇宙的正确方式
  19. android 微信 openid,android 微信登陆手把手教学获取openid
  20. 常见的两种python编译器的安装

热门文章

  1. linux在多核处理器上的负载均衡原理
  2. 关闭页面不用提示的方法
  3. 自动创建阿里云抢占式实例
  4. 服务器架设笔记——编译Apache及其插件
  5. linux驱动:i2c驱动(二)
  6. Ruby Metaprogramming
  7. jsp mysql 图片路径,请教JSP中怎么向MySql中存入和取出图片
  8. java 卖票问题_Java之多线程窗口卖票问题(Thread)
  9. windows游戏编程_少儿编程该怎么学?看看帕拉卡3D动画编程创始人李西峙分享七个核心...
  10. 自定义html托管,10分钟搞定“傻瓜式”的静态网站搭建托管之旅