array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 服务端程序线程运行信息管理器 - 爱码网

 

 

现在的服务端程序都是多线程的并且其中有大量的工作现场,如何知道每一个工作线程都在干什么?

在服务端程序实现时必须考虑到一些工作需要耗时较长,甚至可能因为死锁等原因导致一些线程进入了某个调用就退步出来的情况,这个时候增加远程连接对服务端程序内部工作状态的查看功能就必不可少了;

本文基于一个服务端程序的线程运行信息管理的实现介绍原理并给出代码

首先我们要考虑到对线程运行信息的访问不能有频繁的锁操作,其次该信息应该能够根据使用情况自动的为每个需要运行信息的线程分配的存储空间并且各不关联,同时需要所有线程的运行信息能够进行遍历,这样就可以考虑这样实现:

  1. 线程的运行信息存储在线程专用存储中,这样不但数据各个线程分开避免了锁的开销,而且方便编写程序(就像使用一个单独的成员变量一样);
  2. 每一个线程的运行信息结构的指针和线程的ID关联起来放置到哈希映射表中,这样便于对所有使用了运行信息的线程进行遍历;
  3. 由于运行信息记录的是一个工作线程的工作过程,因此是一个开始工作时记录,结束工作时清除的类似栈的数据信息;

同时因为运行信息只记录需要时间较长并且可能引起无法返回的工作,所以信息量不会很大,因此使用使用一个固定大小的结构定义出来,然后使用 ACE_TSS 模板来自动进行线程专用存储的管理,同时使用 ACE_Hash_Map_Manager 来关联线程ID和运行信息指针;

下面是实现:


#pragma once

//==================================================================================================
//    概述:
//        线程状态管理器:管理各个线程的运行状态
//==================================================================================================
struct StatusManager
{
public:
    
//----------------------------------------------------------------------------------------------
    
//    概述:
    
//        设置线程的运行信息
    
//----------------------------------------------------------------------------------------------
    static ACE_UINT32 SetRunInfo( const char * RunInfo )
    {
        TASK_RUN_INFO 
& TaskRunInfo = GetInstance( ).GetTaskRunInfo( );
        CHK_EXP_RUN( TaskRunInfo.Number 
>= MAX_TRI_NUMBER , MAX_TRI_NUMBER );

        TASK_RUN_STATUS 
& Status = TaskRunInfo.Status[ TaskRunInfo.Number ];
        strncpy( Status.String , RunInfo , MAX_TRI_LENGTH 
- 1 );
        ACE_OS::gettimeofday( ).msec( Status.DateTime );
        
return TaskRunInfo.Number ++ ;
    }

    
//----------------------------------------------------------------------------------------------
    
//    概述:
    
//        清除线程的运行信息
    
//----------------------------------------------------------------------------------------------
    static ACE_UINT32 ClrRunInfo( ACE_UINT32 RunInfoID )
    {
        TASK_RUN_INFO 
& TaskRunInfo = GetInstance( ).GetTaskRunInfo( );
        CHK_EXP_RUN( TaskRunInfo.Number 
<= RunInfoID , RunInfoID );
        
        
//    消除指定信息及其以后的信息
        return TaskRunInfo.Number = RunInfoID ;
    }

protected:
    
//----------------------------------------------------------------------------------------------
    
//    概述:
    
//        定义数据结构和哈希映射类型
    
//----------------------------------------------------------------------------------------------
    enum TASK_RUN_INFO_CAPACITY { MAX_TRI_NUMBER = 255 , MAX_TRI_LENGTH = 120 };
    
struct TASK_RUN_STATUS { ACE_UINT64 DateTime; char String[ MAX_TRI_LENGTH ]; };
    
struct TASK_RUN_INFO { ACE_UINT32 Number; TASK_RUN_STATUS Status[ MAX_TRI_NUMBER ]; };
    
struct S_TASK_RUN_INFO : public TASK_RUN_INFO { S_TASK_RUN_INFO( ) { memset( this , 0 ,sizeof* this ) ); } };
    typedef ACE_Hash_Map_Manager
< ACE_thread_t , TASK_RUN_INFO * , ACE_Thread_Mutex > ACE_Hash_Map_Task_Run_Info;

    
//----------------------------------------------------------------------------------------------
    
//    概述:
    
//        获取线程运行信息结构引用
    
//----------------------------------------------------------------------------------------------
    inline TASK_RUN_INFO & GetTaskRunInfo( )
    {
        ACE_thread_t Thread 
= ACE_Thread_Manager::instance( )->thr_self( );
        S_TASK_RUN_INFO 
* lpTaskRunInfo = TaskRunInfo;
        HashRunInfo.rebind( Thread , lpTaskRunInfo );
        
return * lpTaskRunInfo ;
    }

    
//----------------------------------------------------------------------------------------------
    
//    概述:
    
//        获取状态管理器
    
//----------------------------------------------------------------------------------------------
    static StatusManager & GetInstance( )
    {
        
static StatusManager sxStatusManager;
        
return sxStatusManager;
    }

protected:
    
//----------------------------------------------------------------------------------------------
    ACE_Hash_Map_Task_Run_Info HashRunInfo;
    ACE_TSS
< S_TASK_RUN_INFO > TaskRunInfo;
};

//==================================================================================================
//    概述:
//        任务运行信息自动设置清除类
//==================================================================================================
struct DPS_Task_Run_Info
{
    inline DPS_Task_Run_Info( 
const char * Format , 服务端程序线程运行信息管理器 )
    {
        
char RunInfo[ 128 ] ="" }; 
        va_list args; va_start( args , Format );
        vsnprintf( RunInfo , 
120 , Format , args );
        m_nTaskRunInfo 
= StatusManager::SetRunInfo( RunInfo );
    }

    inline 
~DPS_Task_Run_Info( )
    {
        StatusManager::ClrRunInfo( m_nTaskRunInfo );
    }

    ACE_UINT32 m_nTaskRunInfo;
};

//==================================================================================================
//    概述:
//        根据编译选项来控制是否需要运行时任务信息
//==================================================================================================
#ifdef _DPS_DISABLE_TASK_RUN_INFO_
#    define TASK_RUN_INFO( Format , 服务端程序线程运行信息管理器 )
#    define TASK_RUN_INFO_EX( Name , Format , 服务端程序线程运行信息管理器 )
#else
#    define TASK_RUN_INFO( Format , 服务端程序线程运行信息管理器 ) DPS_Task_Run_Info xTaskRunInfo( Format , __VA_ARGS__ )
#    define TASK_RUN_INFO_EX( Name , Format , 服务端程序线程运行信息管理器 ) DPS_Task_Run_Info Name( Format , __VA_ARGS__ )
#endif

 

由于宏中使用了可变参数,所以需要 VC 7.1 及其以上版本才能正常编译,如果不需要可变参数以及信息的格式化功能,那么稍作修改即可使用在 VC6 上

相关文章: