之前一直是使用C语言,前段时间转做C++。无论使用什么语言,多线程编程都是不可或缺的。最近项目中又用到了线程,现在将线程的封装做出总结:
1、线程类中应该包含线程ID、线程的状态以及线程基本操作等。
2、线程需要的基本操作都差不多,唯一不同的是线程执行的函数体。因此大多数操作都可以写在基类中,当需要使用线程时,只需要继承该基类并且实现run函数即可。
基类的定义如下:
1 /*线程基类,封装了线程常用的操作,以后需要使用线程时,只需要继承该类并实现Run函数既可*/ 2 class CThread { 3 public: 4 5 /*如果不需要为线程传参数,则可以使用这个构造函数*/ 6 CThread() 7 { 8 m_ThreadId = 0; 9 10 m_iThreadStatus = 0; 11 12 m_vpParameter = NULL; 13 } 14 15 /*重载构造函数,该构造函数可以为线程传参数*/ 16 CThread(void *vpParameter) 17 { 18 m_ThreadId = 0; 19 20 m_iThreadStatus = 0; 21 22 m_vpParameter = cpParameter; 23 } 24 25 virtual ~CThread(); 26 27 /*线程的启动函数,在该函数中将会创建线程*/ 28 int Start(void *Parameter); 29 30 /*线程的回调函数,在该函数中只是转调run函数*/ 31 static void *ThreadCall(void *vpParameter); 32 33 /*获取线程ID*/ 34 pthread_t GetThreadId() 35 { 36 return this->m_ThreadId; 37 } 38 39 /*获取线程状态*/ 40 int GetThreadStatus() 41 { 42 return m_iThreadStatus; 43 } 44 45 /*获取线程状态*/ 46 int GetThreadStatus(); 47 48 /*线程真正工作的函数,这个函数需要在派生类中实现*/ 49 virtual void *Run(void *Parameter) = 0; 50 protected: 51 52 //线程的Id号 53 pthread_t m_ThreadId; 54 55 //线程状态 56 int m_iThreadStatus; 57 58 //线程参数 59 void* m_vpParameter; 60 }; 61 62 inline pthread_t CThread::GetThreadId() 63 { 64 return this->m_ThreadId; 65 }
在线程的回调函数中,只是转掉函数Run。这样设计的原因是因为在C++的回调函数必须是全局函数或者是静态成员函数,否则编译不会通过。而全局函数没有虚函数一说,也没有继承一说(静态函数也没有,静态函数只是限制了作用域的全局函数)。Start函数与线程的回调函数实现如下:
1 int CThread::Start(void *vpParameter) 2 { 3 int ret = pthread_create(&(this->m_ThreadId), NULL, CThread::ThreadCall, vpParameter);//该函数中创建线程 4 if(0 == ret) 5 { 6 return TRUE; 7 } 8 9 return FAULT; 10 } 11 12 void *CThread::ThreadCall(void *vpParameter)//线程回调函数 13 { 14 void *vpRet; 15 CThread *pObj = static_cast<CThread *>(vpParameter);//将指针强制性转化成对象 16 17 18 vpRet = pObj->Run(m_vpParameter);//调用线程正在执行的函数 19 20 return vpRet; 21 };
总结:这样设计以后,程序中如果需要其它使用其它线程,可以继承该基类,然后实现Run函数即可。如果需要线程等待等操作则需要在里面添加内容。