【C/C++开发】C++ Thread对象封装
Pthread库是posix linux的线程库,调用接口如下,我们模仿JDK,对Thread进行封装,具体的业务逻辑只需要如同Thread一样实现run方法即可。
线程操纵函数(简介起见,省略参数)
pthread_create():创建一个线程
pthread_exit():终止当前线程
pthread_cancel():中断另外一个线程的运行
pthread_join():阻塞当前的线程,直到另外一个线程运行结束
pthread_attr_init():初始化线程的属性
pthread_attr_setdetachstate():设置脱离状态的属性(决定这个线程在终止时是否可以被结合)
pthread_attr_getdetachstate():获取脱离状态的属性
pthread_attr_destroy():删除线程的属性
pthread_kill():向线程发送一个信号
首先,构造一个run接口如下:
class TC_Runable
{
public:
virtual ~TC_Runable(){};
virtual void run()
= 0;
};
声明线程基础类:
/**
* 线程基类.
* 线程基类,所有自定义线程继承于该类,同时实现run接口即可,
* 可以通过TC_ThreadContorl管理线程。
*/
class TC_Thread : public TC_Runable
{
public:
/**
* @brief 构造函数
*/
TC_Thread();
/**
* @brief 析构函数
*/
virtual ~TC_Thread(){};
/**
* @brief 线程运行
*/
TC_ThreadControl start();
/**
* @brief 获取线程控制类.
*
* @return ThreadControl
*/
TC_ThreadControl getThreadControl() const;
/**
* @brief 线程是否存活.
*
* @return bool 存活返回true,否则返回false
*/
bool isAlive() const;
/**
* @brief 获取线程id.
*
* @return pthread_t 线程id
*/
pthread_t id()
{ return _tid;
}
protected:
/**
* @brief 静态函数, 线程入口.
*
* @param pThread 线程对象
*/
static void threadEntry(TC_Thread *pThread);
/**
* @brief 运行
*/
virtual void run()
= 0;
protected:
/**
* 是否在运行
*/
bool _running;
/**
* 线程ID
*/
pthread_t _tid;
/**
* 线程锁
*/
TC_ThreadLock _lock;
};
根据Pthread提供的接口实现该Thread类。
线程构造函数:
TC_Thread::TC_Thread() : _running( false), _tid(-1)
{
}
初始化tid为-1,线程状态running为false。
线程执行入口,该方法声明的时候必须为静态方法,因为该方法符合pthread_create方法中的函数指针的类型,该方法将会回调thread的具体的子类重载的run方法,thread子类的实例通过指针传递进来。
void TC_Thread::threadEntry( TC_Thread *pThread)
{
pThread->_running = true;
{
TC_ThreadLock::Lock sync(pThread-> _lock);
pThread-> _lock.notifyAll();
}
try
{
pThread->run();
}
catch(...)
{
pThread-> _running = false;
throw;
}
pThread->_running = false;
}
通过调用start方法线程开始执行,但并不负责具体的执行逻辑,所以该方法对于start来说是通过的,是调用pthread_ctreat的地方,在该方法中,会调用this.threadEntity函数,通过其回调this.run()
TC_ThreadControl TC_Thread::start()
{
TC_ThreadLock::Lock sync(_lock);
if(_running)
{
throw TC_ThreadThreadControl_Exception("[TC_Thread::start]
thread has start");
}
int ret
= pthread_create(&_tid ,
0,
( void *(*)( void *))& threadEntry,
( void *) this);
if(ret
!= 0)
{
throw TC_ThreadThreadControl_Exception("[TC_Thread::start]
thread start error", ret);
}
_lock.wait();
return TC_ThreadControl(_tid);
}
获取线程控制工具类
TC_ThreadControl TC_Thread::getThreadControl () const
{
return TC_ThreadControl(_tid);
}
判断线程当前状态。
bool TC_Thread::isAlive() const
{
return _running;
}
整个线程类封装设计的难点在于,如果保证running的同步,我们必须保证线程真正在执行run方法的时候,该running设置为true,也就是说不能单纯的在start中变更该状态,因为此时有可能threadEntity并没有被执行(Pthread_creat)
在start方法中,首先便获取锁并顺序执行,但是start方法并不返回将wait住(3)(因为此事线程提方法并不一定成功执行,也就是说start能够返回的标志是该线程状态必须为running,否则在业务层面执行完start方法紧接着判断线程isalive却返回false会给调用者带来迷茫,甚至导致重复启动),threadEntity执行时表明pthread_create方法已经开始执行了,新线程执行OK,此时该方法将running设置为true(1),并且试图获取锁,此时如果wait已经执行,则获取锁操作可以成功,如果wait不成功,则会阻塞在这里等待wait操作的到来释放锁。
{
TC_ThreadLock::Lock sync(pThread-> _lock);
pThread-> _lock.notifyAll();
}
这个大括号很重要,表示sync的生命周期在大括号结束的时候会释放,锁释放代表着notifyAll生效(真正的通知wait解除阻塞是在锁释放的时候进行的,因为wait需要重新获取锁),此时running为true,start方法可以安全返回了。当方法进行完之后,将running重新设置为false(2)。