在 C++11 发布前,C++语言本身并不支持线程,而是通过 pthread 库来进行支持的,C++11发布后,其语言本身已经支持了线程,且是通过线程类的方式进行提供,使用方法可能参考此篇文章:c++11线程类 。现在C++11及之后版本已经提供了线程类来使用线程,但我们在编译的时候还是需要添加 -lpthread 链接(也许其线程类实现还是得依赖 pthread 库吧,没看过源码还不清楚),那如果不使用c++提供的线程类,我们在实际项目中是如何封装的线程类呢?
以下代码先以 muduo 库里的线程类进行一下讲解,看它是如何封装线程类的,如:
#ifndef __UNI_THREAD_H__
#define __UNI_THREAD_H__#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <pthread.h>class CThread: public boost::noncopyable
{
public:typedef boost::function0<void> threadProc;explicit CThread(const threadProc& proc, std::string threaName);~CThread();void createThread();bool started()const {return mStarted;}pid_t tid() const{return mTid;}const std::string& name()const{return mName;}int join();
private:static void* startThread(void* arg);void runInThread();
private:bool mStarted;pthread_t mPthreadId;pid_t mTid;threadProc funcProc;std::string mName;
};#endif
这是一个线程类的声明,我们看到此类构造函数里就可以绑定要执行的线程函数。它的实现是这样的:
#include <assert.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#include "Thread.h"
#include "CurrentThread.h"namespace detail
{pid_t gettid(){return static_cast<pid_t>(::syscall(SYS_gettid));}
};/****************************** namespace CurrentThread* **************************/
namespace CurrentThread
{__thread int tCachedTid = 0;__thread char tTidString[32];__thread const char *tThreadName = "unknow";};void CurrentThread::cacheTid()
{///第一次调用时会调用系统函数if(tCachedTid == 0){tCachedTid = detail::gettid();snprintf(tTidString, sizeof(tTidString), "%5d ", tCachedTid);}
}bool CurrentThread::isMainThread()
{return tid() == ::getpid();
}/****************************** CThread* **************************/
CThread::CThread(const threadProc& proc, std::string threaName):
mStarted(false),
mPthreadId(-1),
funcProc(proc),
mName(threaName)
{}CThread::~CThread()
{}void CThread::createThread()
{assert(!mStarted);mStarted = true;errno = pthread_create(&mPthreadId, NULL, startThread, this);if(errno < 0){}
}void* CThread::startThread(void* arg)
{CThread *thread = static_cast<CThread*>(arg);thread->runInThread();return nullptr;
}void CThread::runInThread()
{mTid = CurrentThread::tid();if(funcProc){funcProc();}
}int CThread::join()
{assert(mStarted);return pthread_join(mPthreadId, nullptr);
}
可以看到在 createThread() 成员函数里调用了 pthread_create() 进行线程的创建,而且线程函数是此类的一个 static 函数 startThread(void* arg),为什么是 static 类型函数呢?因为函数 pthread_create() 的第 3 个参数是一个函数指针,且是 C 语言类型的函数指针,这里无法传入类的成员函数。实际工作中遇到的是另外一种实现方法,后面会有介绍。所以使用时,只要定义一个CThread 对象,然后调用 createThread() 即可,如:
在 调用 CAsyncLogging::start() 后,线程即刻创建起来,且执行线程函数 threadProc()。
实际工作中遇到线程类是这样的,列举片段:
// 线程类的声明
class CThread
{///其他成员函数bool createThread();/// 线程执行体,是一个纯虚函数,派生的线程类中必须实现此函数,实现各自的行为。virtual void threadProc() = 0;
}
这里最重要的是声明了一个纯虚函数,说明这个类是一个抽象类,只能用作基类。它也有一个 public 成员函数 createThread(),通过此函数创建线程,但这里比上面那个 createThread() 复杂一点,它里面会设置线程的属性、调度策略、线程优先级、线程栈大小等。
ret = pthread_create(&mInternal->mHandle, &attr, threadBody, (void *)mInternal);
它的线程函数也是一个全局函数,最后一个是一个内部的对象,保存着这个线程的相关信息。在线程函数里首先会把这个参数强转成指定类型,然后再进行调用。
pInternal->mOwner->threadProc();
而这个mOwner 就是在CThread 的构造函数里被赋为了 this,就是CThread对象,派生类只要实现 virtual void threadProc(),然后调用 createThread() 后就可以调用到自己的 threadProc() 函数了,这里用到的就是类的虚函数特性了。使用起来也很方便:
#include "Thread.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>class CMyThread: public CThread
{
public:CMyThread();~CMyThread();virtual void threadProc();
};CMyThread::CMyThread(): CThread("myThread")
{}CMyThread::~CMyThread()
{}void CMyThread::threadProc()
{int count = 5;while(count--){sleep(1);printf("in CMyThreadn");}
}int main()
{CMyThread *myThread = new CMyThread();myThread->createThread();sleep(7);return 0;
}
派生类里只要实现 threadProc() 即可,运行结果如:
本文发布于:2024-01-28 03:49:33,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17063849774565.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |