转载于:http://njulinq.blog.51cto.com/1257169/284794
下面我们就来看一下这个线程池是怎么运作的。
线程池类RunnableConsumerThreadPool本身提供的接口很少,主要包括getRunQueue(),start((),stop()等,其他暂时不涉及的就不介绍了,有兴趣的可以自行去阅读相关代码。
从上一篇文章中,知道当构造出一个线程池对象后,就可以向该线程池添加等待调度对象,例如:
- m_runner=newRunnableConsumerThreadPool("TestPool",0.6f,1.0f,10);
- m_runner.start();
- m_runner.getRunQueue().add(runnable);
上述代码中,m_runner被构造出来后,要先启动线程池,即调用其start方法,然后可以开始向线程池的运行队列中添加调度对象了,这里的运行队列在上文中介绍过就是一个先进先出的队列。而调度对象实际上就是实现了Runnable接口的对象。
RunnableConsumerThreadPool的核心其实就在于这个运行队列,它对应类SizingFifoQueue,这个类主要提供了三个方法add(),remove(),adjust()。在调用这个类的add或者remove方法时,都会触发对adjust方法的调用。其核心也就是这个adjust方法,下面看下这个adjust方法。
- privatevoidadjust(){
- inte=size();
- synchronized(m_fibers){
- intalive=livingFiberCount();
- floatratio=(float)e/(float)(alive<=0?1:alive);
- //Neverstopthelastthread!?
- if(alive>1&&ratio<=m_loRatio){
- /*
- *If:
- *1)Fibersgreaterthanone,and...
- *2)ratiolessthanlowwatermark
- */
- Fiberf=null;
- intlast=Fiber.START_PENDING;
- for(Fiberfiber:m_fibers){
- if(fiber!=null){
- switch(fiber.getStatus()){
- caseFiber.RUNNING:
- if(last<Fiber.RUNNING){
- f=fiber;
- last=f.getStatus();
- }
- break;
- caseFiber.STOP_PENDING:
- if(last<Fiber.STOP_PENDING){
- f=null;
- last=Fiber.STOP_PENDING;
- }
- break;
- }
- }
- }
- if(f!=null&&f.getStatus()!=Fiber.STOP_PENDING){
- if(log().isDebugEnabled()){
- log().debug("adjust:callingstoponfiber"+f.getName());
- }
- f.stop();
- }
- }elseif(((alive==0&&e>0)||ratio>m_hiRatio)&&alive<m_maxSize){
- /*
- *If:
- *1a)Fibersequaltozeroandqueuenotempty,or..
- *1a)ratiogreaterthanhiRatio,and...
- *2)Fiberslessthanmaxsize
- */
- for(intx=0;x<m_fibers.length;x++){
- if(m_fibers[x]==null||m_fibers[x].getStatus()==Fiber.STOPPED){
- Fiberf=newFiberThreadImpl(m_poolName+"-fiber"+x);
- f.start();
- m_fibers[x]=f;
- if(log().isDebugEnabled()){
- log().debug("adjust:startedfiber"+f.getName()+"ratio="+ratio+",alive="+alive);
- }
- break;
- }
- }
- }
- }
- }
这段代码对于理解线程池的运行非常重要,所以需要重点讲解一下:
首先其实是需要计算当前运行队列中等待调度对象与线程池中线程数的比值,即第5行中的代码。这里注意,如果当前没有任何线程,则取线程数为1。如果当线程数大于1并且当前比值小于等于低水印值时,那么这种情况代表什么呢?其实就意味着当前等待调度对象已经远远小于线程池中线程的个数,所以需要收回某些线程。第15-33行的循环其实就是在找当前线程池中状态为running的第一个线程,如果找到这个线程,且当前池中没有将要stop的线程即状态为STOP_PENDING的线程,则将该线程停掉。如果这个线程池里面已经有等待停止的线程,则不需要再去额外停止一个将要运行或正在运行的线程。
相反,如果说目前线程池中没有线程,并且存在等待调度对象,或者说等待调度对象与线程数比值已经超过高水印阈值,在这两种情况下,只要当前线程数没有超过线程池最大线程数,则新启动一个线程。
其实代码中的Fiber就对应于一个线程,当它被创建出来后,就不段的去线程池运行队列中取等待调度对象然后执行,当运行队列中没有调度对象时,该线程等待500毫秒,然后重新去取。如果该线程被停止,则将状态标记为STOPPED后退出。
通过上面的代码可以看到线程池中线程的数目随着运行队列中等待调度对象的变化而变化,从而能够根据负载情况自我调节,真正做到了随需而动。
分享到:
相关推荐
OpenNMS是开源网络管理平台,它主要用于监控网络设备、服务和应用程序的性能与可用性。这个"opennms1.12.5-1源码下载"标题指的是该平台的1.12.5-1版本的源代码,允许用户深入理解其内部工作原理,进行定制开发或调试...
openNMS1.6.5源码,最新稳定的版本。OpenNMS是第一个开发在开源模式下的企业级网络管理平台应用。OpenNMS的目标是成为一个真真的分布式、可升级的网络管理平台,尽管它看似一个FCAPS网络管理模型,使之可用于开放...
通过分析`opennms-1.10.3-1`源代码,我们可以学习到网络监控的最佳实践,了解如何设计和实现大规模网络管理解决方案。这对于网络管理员、系统集成商以及对网络管理有兴趣的开发者来说,都是极其宝贵的资源。同时,...
"opennms-source.tar.gz_SNMP_openNMS"这个压缩包,便是OpenNMS源码的载体,它包含了使用SNMP(简单网络管理协议)进行网络监控和管理所需的所有组件。 SNMP,全称Simple Network Management Protocol,是一种广泛...
OpenNMS是一款开源的网络监控系统,用于管理网络设备、服务和应用程序。它提供了一整套功能,包括自动发现网络资源、性能监控、故障检测、报警通知和报告生成。本手册将详细介绍OpenNMS的配置与功能,帮助你充分利用...
OpenNMS-Helm是基于OpenNMS监控系统的Grafana插件,它能够扩展Grafana的功能,以适应更复杂的网络监控需求。OpenNMS-Helm的安装和配置涉及到多个步骤,包括系统的前置安装条件、安装OpenNMS-Helm、启动服务、启用...
opennms 中文 http://www.qoswork.com OpenNMS 官方文档 https://qoswork.github.io/odoc/
OpenNMS Javascript API 用于访问OpenNMS网络监视平台的客户端API。 在代码中使用OpenNMS.js API 中提供了有关入门以及如何使用API的。 完整的API列表可在。 使用OpenNMS.js命令行 安装 运行npm install -g ...
standalone-opennms-1.6.8.jar
通过opennms-ksc-grafana,用户可以充分利用Grafana的可视化优势,对OpenNMS KSC的监控数据进行深度分析和展示,这对于网络运维团队来说,无疑是一种提升效率、优化工作流程的有效手段。无论是日常监控、问题排查,...
为了使用 OpenNMS Modules Manager,你需要先将其克隆或下载到本地,例如,你可以找到名为 "opennms-modules-manager-master" 的压缩包文件,解压后通过 Java 运行环境执行相应的脚本或命令。在执行前,确保你的系统...
PagerDuty-OpenNMS PagerDuty-OpenNMS 是一个由 OpenNMS 运行的脚本,它使用 curl 调用 PagerDuty 集成 API。配置配置本身并不过分复杂: 将附加的脚本放在 $OPENNMS_HOME/contrib/pagerduty 将 API 密钥从...
OpenNMS-IP-发现-供应-适配器可选的Provisioning Adapter,用于将IP接口的自动发现管理为非托管动机找到想要发现并持久存储数据库中所有IP接口,但仅主动监视受监控的服务的OpenNMS用户和操作员是很常见的,这些服务...
厨师食谱,用于管理OpenNMS Horizon的安装和配置。 当前版本支持CentOS 6和7的发行版16、17、18、19、20、21、22、23、24、25、26。 版本号 从OpenNMS Horizon 16开始,该食谱版本的MSB与其支持的OpenNMS ...
OpenNMS-KSC至Grafana 将 KSC报表转换为仪表板。 已针对Grafana 4.x,5.x和6.x进行了测试; 尽管该工具仅在Grafana 5.x或更高版本上在标准输出上提供有关生成的仪表板的信息。 由于Grafana的工作方式不同,它不会...
OpenNMS-阈值-事件-生成器一种基于当前阈值设置生成良好阈值事件定义(和通知)的工具。 要编译该工具,请使用 Maven: mvn install这将生成一个带有依赖项的 JAR,以便能够轻松执行该工具,例如: java -jar ...
OpenNMS-资源-供应-适配器 用于填充定义为复杂 SNMP 表的字符串的其他 MibObject 的配置适配器 要求: 1.0.x OpenNMS 14. 1.1.x OpenNMS 15/16。
OpenNMS集成API 该项目旨在通过引入一个稳定的接口来对其进行编写,从而使其更容易为OpenNMS编写插件和扩展。 然后,OpenNMS和Meridian的版本将实现API的至少一个主要版本。 特征 API的用户当前可以利用以下功能和...
这是一个 MCollective 应用程序文件,它允许 mcollective 生成 OpenNMS 网络管理系统的供应申请。 先决条件版本 >=1.10.0 的正在运行的 OpenNMS 服务器(早期版本中存在一个错误,会导致配置重复节点) 对 ...