用ps aux只能查看到进程,如果进程里面使用了pthread编程,用什么命令才能查询到进程里的线程资源占用?
class CThreadManage { private: CThreadPool* m_Pool; int m_NumOfThread; protected: public: void SetParallelNum(int num); CThreadManage(); CThreadManage(int num); virtual ~CThreadManage(); void Run(CJob* job,void* jobdata); void TerminateAll(void); };
CThreadManage::CThreadManage(){ m_NumOfThread = 10; m_Pool = new CThreadPool(m_NumOfThread); } CThreadManage::CThreadManage(int num){ m_NumOfThread = num; m_Pool = new CThreadPool(m_NumOfThread); } CThreadManage::~CThreadManage(){ if(NULL != m_Pool) delete m_Pool; } void CThreadManage::SetParallelNum(int num){ m_NumOfThread = num; } void CThreadManage::Run(CJob* job,void* jobdata){ m_Pool->Run(job,jobdata); } void CThreadManage::TerminateAll(void){ m_Pool->TerminateAll(); }
class CThread { private: int m_ErrCode; Semaphore m_ThreadSemaphore; //the inner semaphore, which is used to realize unsigned long m_ThreadID; bool m_Detach; //The thread is detached bool m_CreateSuspended; //if suspend after creating char* m_ThreadName; ThreadState m_ThreadState; //the state of the thread protected: void SetErrcode(int errcode){m_ErrCode = errcode;} static void* ThreadFunction(void*); public: CThread(); CThread(bool createsuspended,bool detach); virtual ~CThread(); virtual void Run(void) = 0; void SetThreadState(ThreadState state){m_ThreadState = state;} bool Terminate(void); //Terminate the threa bool Start(void); //Start to execute the thread void Exit(void); bool Wakeup(void); ThreadState GetThreadState(void){return m_ThreadState;} int GetLastError(void){return m_ErrCode;} void SetThreadName(char* thrname){strcpy(m_ThreadName,thrname);} char* GetThreadName(void){return m_ThreadName;} int GetThreadID(void){return m_ThreadID;} bool SetPriority(int priority); int GetPriority(void); int GetConcurrency(void); void SetConcurrency(int num); bool Detach(void); bool Join(void); bool Yield(void); int Self(void); };
class CThreadPool { friend class CWorkerThread; private: unsigned int m_MaxNum; //the max thread num that can create at the same time unsigned int m_AvailLow; //The min num of idle thread that shoule kept unsigned int m_AvailHigh; //The max num of idle thread that kept at the same time unsigned int m_AvailNum; //the normal thread num of idle num; unsigned int m_InitNum; //Normal thread num; protected: CWorkerThread* GetIdleThread(void); void AppendToIdleList(CWorkerThread* jobthread); void MoveToBusyList(CWorkerThread* idlethread); void MoveToIdleList(CWorkerThread* busythread); void DeleteIdleThread(int num); void CreateIdleThread(int num); public: CThreadMutex m_BusyMutex; //when visit busy list,use m_BusyMutex to lock and unlock CThreadMutex m_IdleMutex; //when visit idle list,use m_IdleMutex to lock and unlock CThreadMutex m_JobMutex; //when visit job list,use m_JobMutex to lock and unlock CThreadMutex m_VarMutex; CCondition m_BusyCond; //m_BusyCond is used to sync busy thread list CCondition m_IdleCond; //m_IdleCond is used to sync idle thread list CCondition m_IdleJobCond; //m_JobCond is used to sync job list CCondition m_MaxNumCond; vector<CWorkerThread*> m_ThreadList; vector<CWorkerThread*> m_BusyList; //Thread List vector<CWorkerThread*> m_IdleList; //Idle List CThreadPool(); CThreadPool(int initnum); virtual ~CThreadPool(); void SetMaxNum(int maxnum){m_MaxNum = maxnum;} int GetMaxNum(void){return m_MaxNum;} void SetAvailLowNum(int minnum){m_AvailLow = minnum;} int GetAvailLowNum(void){return m_AvailLow;} void SetAvailHighNum(int highnum){m_AvailHigh = highnum;} int GetAvailHighNum(void){return m_AvailHigh;} int GetActualAvailNum(void){return m_AvailNum;} int GetAllNum(void){return m_ThreadList.size();} int GetBusyNum(void){return m_BusyList.size();} void SetInitNum(int initnum){m_InitNum = initnum;} int GetInitNum(void){return m_InitNum;} void TerminateAll(void); void Run(CJob* job,void* jobdata); }; CThreadPool::CThreadPool() { m_MaxNum = 50; m_AvailLow = 5; m_InitNum=m_AvailNum = 10 ; m_AvailHigh = 20; m_BusyList.clear(); m_IdleList.clear(); for(int i=0;i<m_InitNum;i++){ CWorkerThread* thr = new CWorkerThread(); thr->SetThreadPool(this); AppendToIdleList(thr); thr->Start(); } } CThreadPool::CThreadPool(int initnum) { assert(initnum>0 && initnum<=30); m_MaxNum = 30; m_AvailLow = initnum-10>0?initnum-10:3; m_InitNum=m_AvailNum = initnum ; m_AvailHigh = initnum+10; m_BusyList.clear(); m_IdleList.clear(); for(int i=0;i<m_InitNum;i++){ CWorkerThread* thr = new CWorkerThread(); AppendToIdleList(thr); thr->SetThreadPool(this); thr->Start(); //begin the thread,the thread wait for job } } CThreadPool::~CThreadPool() { TerminateAll(); } void CThreadPool::TerminateAll() { for(int i=0;i < m_ThreadList.size();i++) { CWorkerThread* thr = m_ThreadList[i]; thr->Join(); } return; } CWorkerThread* CThreadPool::GetIdleThread(void) { while(m_IdleList.size() ==0 ) m_IdleCond.Wait(); m_IdleMutex.Lock(); if(m_IdleList.size() > 0 ) { CWorkerThread* thr = (CWorkerThread*)m_IdleList.front(); printf("Get Idle thread %dn",thr->GetThreadID()); m_IdleMutex.Unlock(); return thr; } m_IdleMutex.Unlock(); return NULL; } //add an idle thread to idle list void CThreadPool::AppendToIdleList(CWorkerThread* jobthread) { m_IdleMutex.Lock(); m_IdleList.push_back(jobthread); m_ThreadList.push_back(jobthread); m_IdleMutex.Unlock(); } //move and idle thread to busy thread void CThreadPool::MoveToBusyList(CWorkerThread* idlethread) { m_BusyMutex.Lock(); m_BusyList.push_back(idlethread); m_AvailNum--; m_BusyMutex.Unlock(); m_IdleMutex.Lock(); vector<CWorkerThread*>::iterator pos; pos = find(m_IdleList.begin(),m_IdleList.end(),idlethread); if(pos !=m_IdleList.end()) m_IdleList.erase(pos); m_IdleMutex.Unlock(); } void CThreadPool::MoveToIdleList(CWorkerThread* busythread) { m_IdleMutex.Lock(); m_IdleList.push_back(busythread); m_AvailNum++; m_IdleMutex.Unlock(); m_BusyMutex.Lock(); vector<CWorkerThread*>::iterator pos; pos = find(m_BusyList.begin(),m_BusyList.end(),busythread); if(pos!=m_BusyList.end()) m_BusyList.erase(pos); m_BusyMutex.Unlock(); m_IdleCond.Signal(); m_MaxNumCond.Signal(); } //create num idle thread and put them to idlelist void CThreadPool::CreateIdleThread(int num) { for(int i=0;i<num;i++){ CWorkerThread* thr = new CWorkerThread(); thr->SetThreadPool(this); AppendToIdleList(thr); m_VarMutex.Lock(); m_AvailNum++; m_VarMutex.Unlock(); thr->Start(); //begin the thread,the thread wait for job } } void CThreadPool::DeleteIdleThread(int num) { printf("Enter into CThreadPool::DeleteIdleThreadn"); m_IdleMutex.Lock(); printf("Delete Num is %dn",num); for(int i=0;i<num;i++){ CWorkerThread* thr; if(m_IdleList.size() > 0 ){ thr = (CWorkerThread*)m_IdleList.front(); printf("Get Idle thread %dn",thr->GetThreadID()); } vector<CWorkerThread*>::iterator pos; pos = find(m_IdleList.begin(),m_IdleList.end(),thr); if(pos!=m_IdleList.end()) m_IdleList.erase(pos); m_AvailNum--; printf("The idle thread available num:%d n",m_AvailNum); printf("The idlelist num:%d n",m_IdleList.size()); } m_IdleMutex.Unlock(); } void CThreadPool::Run(CJob* job,void* jobdata) { assert(job!=NULL); //if the busy thread num adds to m_MaxNum,so we should wait if(GetBusyNum() == m_MaxNum) m_MaxNumCond.Wait(); if(m_IdleList.size()<m_AvailLow) { if(GetAllNum()+m_InitNum-m_IdleList.size() < m_MaxNum ) CreateIdleThread(m_InitNum-m_IdleList.size()); else CreateIdleThread(m_MaxNum-GetAllNum()); } CWorkerThread* idlethr = GetIdleThread(); if(idlethr !=NULL) { idlethr->m_WorkMutex.Lock(); MoveToBusyList(idlethr); idlethr->SetThreadPool(this); job->SetWorkThread(idlethr); printf("Job is set to thread %d n",idlethr->GetThreadID()); idlethr->SetJob(job,jobdata); } }
for(int i=0;i<m_InitNum;i++) { CWorkerThread* thr = new CWorkerThread(); AppendToIdleList(thr); thr->SetThreadPool(this); thr->Start(); //begin the thread,the thread wait for job }
if(GetAllNum()+m_InitNum-m_IdleList.size() < m_MaxNum ) CreateIdleThread(m_InitNum-m_IdleList.size()); else CreateIdleThread(m_MaxNum-GetAllNum());
class CWorkerThread:public CThread { private: CThreadPool* m_ThreadPool; CJob* m_Job; void* m_JobData; CThreadMutex m_VarMutex; bool m_IsEnd; protected: public: CCondition m_JobCond; CThreadMutex m_WorkMutex; CWorkerThread(); virtual ~CWorkerThread(); void Run(); void SetJob(CJob* job,void* jobdata); CJob* GetJob(void){return m_Job;} void SetThreadPool(CThreadPool* thrpool); CThreadPool* GetThreadPool(void){return m_ThreadPool;} }; CWorkerThread::CWorkerThread() { m_Job = NULL; m_JobData = NULL; m_ThreadPool = NULL; m_IsEnd = false; } CWorkerThread::~CWorkerThread() { if(NULL != m_Job) delete m_Job; if(m_ThreadPool != NULL) delete m_ThreadPool; } void CWorkerThread::Run() { SetThreadState(THREAD_RUNNING); for(;;) { while(m_Job == NULL) m_JobCond.Wait(); m_Job->Run(m_JobData); m_Job->SetWorkThread(NULL); m_Job = NULL; m_ThreadPool->MoveToIdleList(this); if(m_ThreadPool->m_IdleList.size() > m_ThreadPool->GetAvailHighNum()) { m_ThreadPool->DeleteIdleThread(m_ThreadPool->m_IdleList.size()-m_T hreadPool->GetInitNum()); } m_WorkMutex.Unlock(); } } void CWorkerThread::SetJob(CJob* job,void* jobdata) { m_VarMutex.Lock(); m_Job = job; m_JobData = jobdata; job->SetWorkThread(this); m_VarMutex.Unlock(); m_JobCond.Signal(); } void CWorkerThread::SetThreadPool(CThreadPool* thrpool) { m_VarMutex.Lock(); m_ThreadPool = thrpool; m_VarMutex.Unlock(); }
class CJob { private: int m_JobNo; //The num was assigned to the job char* m_JobName; //The job name CThread *m_pWorkThread; //The thread associated with the job public: CJob( void ); virtual ~CJob(); int GetJobNo(void) const { return m_JobNo; } void SetJobNo(int jobno){ m_JobNo = jobno;} char* GetJobName(void) const { return m_JobName; } void SetJobName(char* jobname); CThread *GetWorkThread(void){ return m_pWorkThread; } void SetWorkThread ( CThread *pWorkThread ){ m_pWorkThread = pWorkThread; } virtual void Run ( void *ptr ) = 0; }; CJob::CJob(void) :m_pWorkThread(NULL) ,m_JobNo(0) ,m_JobName(NULL) { } CJob::~CJob(){ if(NULL != m_JobName) free(m_JobName); } void CJob::SetJobName(char* jobname) { if(NULL !=m_JobName) { free(m_JobName); m_JobName = NULL; } if(NULL !=jobname) { m_JobName = (char*)malloc(strlen(jobname)+1); strcpy(m_JobName,jobname); } }
class CXJob:public CJob { public: CXJob(){i=0;} ~CXJob(){} void Run(void* jobdata) { printf("The Job comes from CXJOB\n"); sleep(2); } }; class CYJob:public CJob { public: CYJob(){i=0;} ~CYJob(){} void Run(void* jobdata) { printf("The Job comes from CYJob\n"); } }; main() { CThreadManage* manage = new CThreadManage(10); for(int i=0;i<40;i++) { CXJob* job = new CXJob(); manage->Run(job,NULL); } sleep(2); CYJob* job = new CYJob(); manage->Run(job,NULL); manage->TerminateAll(); }
我设计这个线程池的初衷是为了与socket对接的。线程池的实现千变万化,我得这个并不一定是最好的,但却是否和我心目中需求模型的。现把部分设计思路和代码贴出,以期抛砖引玉。个人比较喜欢搞开源,所以大家如果觉得有什么需要改善的地方,欢迎给予评论。思前想后,也没啥设计图能表达出设计思想,就把类图贴出来吧。
类图设计如下:
Command类是我们的业务类。这个类里只能存放简单的内置类型,这样方便与socket的直接传输。我定义了一个cmd_成员用于存放命令字,arg_用于存放业务的参数。这个参数可以使用分隔符来分隔各个参数。我设计的只是简单实现,如果有序列化操作了,完全不需要使用我这种方法啦。
ThreadProcess就是业务处理类,这里边定义了各个方法用于进行业务处理,它将在ThreadPool中的Process函数中调用。
ThreadPool就是我们的线程池类。其中的成员变量都是静态变量,Process就是线程处理函数。
#define MAX_THREAD_NUM 50 // 该值目前需要设定为初始线程数的整数倍
#define ADD_FACTOR 40 // 该值表示一个线程可以处理的最大任务数
#define THREAD_NUM 10 // 初始线程数
bshutdown_:用于线程退出。
command_:用于存放任务队列
command_cond_:条件变量
command_mutex_:互斥锁
icurr_thread_num_:当前线程池中的线程数
thread_id_map_:这个map用于存放线程对应的其它信息,我只存放了线程的状态,0为正常,1为退出。还可以定义其它的结构来存放更多的信息,例如存放套接字。
InitializeThreads:用于初始化线程池,先创建THREAD_NUM个线程。后期扩容也需要这个函数。
Process:线程处理函数,这里边会调用AddThread和DeleteThread在进行线程池的伸缩。
AddWork:往队列中添加一个任务。
ThreadDestroy:线程销毁函数。
AddThread:扩容THREAD_NUM个线程
DeleteThread:如果任务队列为空,则将原来的线程池恢复到THREAD_NUM个。这里可以根据需要进行修改。
以下贴出代码以供大家参考。
command.h
#ifndef COMMAND_H_ #define COMMAND_H_ class Command { public: int get_cmd(); char* get_arg(); void set_cmd(int cmd); void set_arg(char* arg); private: int cmd_; char arg_[65]; }; #endif /* COMMAND_H_ */
command.cpp
#include <string.h> #include "command.h" int Command::get_cmd() { return cmd_; } char* Command::get_arg() { return arg_; } void Command::set_cmd(int cmd) { cmd_ = cmd; } void Command::set_arg(char* arg) { if(NULL == arg) { return; } strncpy(arg_,arg,64); arg_[64] = '\0'; }
thread_process.h
#ifndef THREAD_PROCESS_H_ #define THREAD_PROCESS_H_ class ThreadProcess { public: void Process0(void* arg); void Process1(void* arg); void Process2(void* arg); }; #endif /* THREAD_PROCESS_H_ */
thread_process.cpp
#include <pthread.h> #include <stdio.h> #include <unistd.h> #include "thread_process.h" void ThreadProcess::Process0(void* arg) { printf("thread %u is starting process %s\n",pthread_self(),arg); usleep(100*1000); } void ThreadProcess::Process1(void* arg) { printf("thread %u is starting process %s\n",pthread_self(),arg); usleep(100*1000); } void ThreadProcess::Process2(void* arg) { printf("thread %u is starting process %s\n",pthread_self(),arg); usleep(100*1000); }
thread_pool.h
#ifndef THREAD_POOL_H_ #define THREAD_POOL_H_ #include <map> #include <vector> #include "command.h" #define MAX_THREAD_NUM 50 // 该值目前需要设定为初始线程数的整数倍 #define ADD_FACTOR 40 // 该值表示一个线程可以处理的最大任务数 #define THREAD_NUM 10 // 初始线程数 class ThreadPool { public: ThreadPool() {}; static void InitializeThreads(); void AddWork(Command command); void ThreadDestroy(int iwait = 2); private: static void* Process(void* arg); static void AddThread(); static void DeleteThread(); static bool bshutdown_; static int icurr_thread_num_; static std::map<pthread_t,int> thread_id_map_; static std::vector<Command> command_; static pthread_mutex_t command_mutex_; static pthread_cond_t command_cond_; }; #endif /* THREAD_POOL_H_ */
thread_pool.cpp
#include <pthread.h> #include <stdlib.h> #include "thread_pool.h" #include "thread_process.h" #include "command.h" bool ThreadPool::bshutdown_ = false; int ThreadPool::icurr_thread_num_ = THREAD_NUM; std::vector<Command> ThreadPool::command_; std::map<pthread_t,int> ThreadPool::thread_id_map_; pthread_mutex_t ThreadPool::command_mutex_ = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t ThreadPool::command_cond_ = PTHREAD_COND_INITIALIZER; void ThreadPool::InitializeThreads() { for (int i = 0; i < THREAD_NUM ; ++i) { pthread_t tempThread; pthread_create(&tempThread, NULL, ThreadPool::Process, NULL); thread_id_map_[tempThread] = 0; } } void* ThreadPool::Process(void* arg) { ThreadProcess threadprocess; Command command; while (true) { pthread_mutex_lock(&command_mutex_); // 如果线程需要退出,则此时退出 if (1 == thread_id_map_[pthread_self()]) { pthread_mutex_unlock(&command_mutex_); printf("thread %u will exit\n", pthread_self()); pthread_exit(NULL); } // 当线程不需要退出且没有需要处理的任务时,需要缩容的则缩容,不需要的则等待信号 if (0 == command_.size() && !bshutdown_) { if(icurr_thread_num_ > THREAD_NUM) { DeleteThread(); if (1 == thread_id_map_[pthread_self()]) { pthread_mutex_unlock(&command_mutex_); printf("thread %u will exit\n", pthread_self()); pthread_exit(NULL); } } pthread_cond_wait(&command_cond_,&command_mutex_); } // 线程池需要关闭,关闭已有的锁,线程退出 if(bshutdown_) { pthread_mutex_unlock (&command_mutex_); printf ("thread %u will exit\n", pthread_self ()); pthread_exit (NULL); } // 如果线程池的最大线程数不等于初始线程数,则表明需要扩容 if(icurr_thread_num_ < command_.size())) { AddThread(); } // 从容器中取出待办任务 std::vector<Command>::iterator iter = command_.begin(); command.set_arg(iter->get_arg()); command.set_cmd(iter->get_cmd()); command_.erase(iter); pthread_mutex_unlock(&command_mutex_); // 开始业务处理 switch(command.get_cmd()) { case 0: threadprocess.Process0(command.get_arg()); break; case 1: threadprocess.Process1(command.get_arg()); break; case 2: threadprocess.Process2(command.get_arg()); break; default: break; } } return NULL; // 完全为了消除警告(eclipse编写的代码,警告很烦人) } void ThreadPool::AddWork(Command command) { bool bsignal = false; pthread_mutex_lock(&command_mutex_); if (0 == command_.size()) { bsignal = true; } command_.push_back(command); pthread_mutex_unlock(&command_mutex_); if (bsignal) { pthread_cond_signal(&command_cond_); } } void ThreadPool::ThreadDestroy(int iwait) { while(0 != command_.size()) { sleep(abs(iwait)); } bshutdown_ = true; pthread_cond_broadcast(&command_cond_); std::map<pthread_t,int>::iterator iter = thread_id_map_.begin(); for (; iter!=thread_id_map_.end(); ++iter) { pthread_join(iter->first,NULL); } pthread_mutex_destroy(&command_mutex_); pthread_cond_destroy(&command_cond_); } void ThreadPool::AddThread() { if(((icurr_thread_num_*ADD_FACTOR) < command_.size()) && (MAX_THREAD_NUM != icurr_thread_num_)) { InitializeThreads(); icurr_thread_num_ += THREAD_NUM; } } void ThreadPool::DeleteThread() { int size = icurr_thread_num_ - THREAD_NUM; std::map<pthread_t,int>::iterator iter = thread_id_map_.begin(); for(int i=0; i<size; ++i,++iter) { iter->second = 1; } }
main.cpp
#include "thread_pool.h" #include "command.h" int main() { ThreadPool thread_pool; thread_pool.InitializeThreads(); Command command; char arg[8] = {0}; for(int i=1; i<=1000; ++i) { command.set_cmd(i%3); sprintf(arg,"%d",i); command.set_arg(arg); thread_pool.AddWork(command); } sleep(10); // 用于测试线程池缩容 thread_pool.ThreadDestroy(); return 0; }
代码是按照google的开源c++编码规范编写。大家可以通过改变那几个宏的值来调整线程池。有问题大家一起讨论。
C++语言: #include<iostream> #include "Thread.h" class MyThreadClass: public Thread { private: int a; public: MyThreadClass( ){ a = 0; } ~MyThreadClass(){ } virtual void run(); }; void Receiver::run(){ a++; std::cout<<a<<std::endl; } int main(int argc, char * argv[]) { MyThreadClass myThread; myThread.start();//创建了一个线程,运行函数run() myThread.join();//等待线程结束 return 0; } 下面是Thread类的实现,为了阅读清晰,删减了很多内容 C++语言: Thread.h #ifndef COMMUNITCATE_H #define COMMUNITCATE_H #include "pthread.h" class Thread { protected: pthread_t _tid; static void* run0(void* opt); void* run1();//如果类中有保存线程状态的变量,可以在这个函数中可以进行更改操作 public: Thread(); ~Thread(); /** * 创建线程,线程函数是 run0 * * @return 成功返回 ture 否则返回 false */ bool start(); /** * join this thread * */ void join(); virtual void run(){ } }; #endif C++语言: Thread.cpp #include "Thread.h" Thread::Thread(){ } Thread::~Thread(){ } void* Thread::run0(void* opt) { Thread* p = (Thread*) opt; p->run1(); return p; } void* Thread::run1() { _tid = pthread_self(); run(); _tid = 0; pthread_exit(NULL); } bool Thread::start() { return pthread_create(&_tid, NULL, run0, this) == 0; } void Thread::join() { if( _tid > 0 ){ pthread_join(_tid, NULL); } }