目录
Q:CBE是多线程的吗?可否部署在多台物理机上?
A:CBE采用的是单线程(当然db读写等特殊任务依然会另开临时线程处理)多进程结构,不同的进程可以部署在不同的物理机上。理论上通过扩展机器数量和配置就可以扩展负载规模。
一、线程池线程生成
线程池实现在thread工程的threadpool类内.
由ThreadPool ->实例化 Thread实现
生成指定数量的线程
bool ThreadPool::createThreadPool(uint32 inewThreadCount,
uint32 inormalMaxThreadCount, uint32 imaxThreadCount)
{
assert(!isInitialize_);
INFO_MSG("ThreadPool::createThreadPool: creating threadpool...\n");
extraNewAddThreadCount_ = inewThreadCount;
normalThreadCount_ = inormalMaxThreadCount;
maxThreadCount_ = imaxThreadCount;
for(uint32 i=0; i<normalThreadCount_; ++i)
{
TPThread* tptd = createThread(0);
if(!tptd)
{
ERROR_MSG("ThreadPool::createThreadPool: error! \n");
return false;
}
currentFreeThreadCount_++;
currentThreadCount_++;
freeThreadList_.push_back(tptd);
allThreadList_.push_back(tptd);
}
INFO_MSG(fmt::format("ThreadPool::createThreadPool: successfully({0}), "
"newThreadCount={1}, normalMaxThreadCount={2}, maxThreadCount={3}\n",
currentThreadCount_, extraNewAddThreadCount_, normalThreadCount_, maxThreadCount_));
isInitialize_ = true;
KBEngine::sleep(100);
return true;
}
生成TPThread类对象
TPThread* ThreadPool::createThread(int threadWaitSecond, bool threadStartsImmediately)
{
TPThread* tptd = new TPThread();
if (threadStartsImmediately)
tptd->createThread();
return tptd;
}
调用API生成线程,Windows使用_beginthreadex, Linux使用pthread_create
THREAD_ID TPThread::createThread(void)
{
#if KBE_PLATFORM == PLATFORM_WIN32
tidp_ = (THREAD_ID)_beginthreadex(NULL, 0,
&TPThread::threadFunc, (void*)this, NULL, 0);
#else
if(pthread_create(&tidp_, NULL, TPThread::threadFunc,
(void*)this)!= 0)
{
ERROR_MSG("createThread error!");
}
#endif
return tidp_;
}
二、线程回调函数
线程回调函数实现,通过参数arg把类指针传递进来
可以看到处理任务都是 tptd->processTask(task);这里
#if KBE_PLATFORM == PLATFORM_WIN32
unsigned __stdcall TPThread::threadFunc(void *arg)
#else
void* TPThread::threadFunc(void* arg)
#endif
{
TPThread * tptd = static_cast<TPThread*>(arg);
ThreadPool* pThreadPool = tptd->threadPool();
bool isRun = true;
tptd->reset_done_tasks();
#if KBE_PLATFORM == PLATFORM_WIN32
#else
pthread_detach(pthread_self());
#endif
tptd->onStart();
while(isRun)
{
if(tptd->task() != NULL)
{
isRun = true;
}
else
{
tptd->reset_done_tasks();
isRun = tptd->onWaitCondSignal();
}
if(!isRun || pThreadPool->isDestroyed())
{
if(!pThreadPool->hasThread(tptd))
tptd = NULL;
goto __THREAD_END__;
}
TPTask * task = tptd->task();
if(task == NULL)
continue;
tptd->state_ = THREAD_STATE_BUSY;
while(task && !tptd->threadPool()->isDestroyed())
{
tptd->inc_done_tasks();
tptd->onProcessTaskStart(task);
tptd->processTask(task);
tptd->onProcessTaskEnd(task);
// 尝试继续从任务队列里取出一个繁忙的未处理的任务
TPTask * task1 = tptd->tryGetTask();
if(!task1)
{
tptd->state_ = THREAD_STATE_PENDING;
tptd->onTaskCompleted();
break;
}
else
{
pThreadPool->addFiniTask(task);
task = task1;
tptd->task(task1);
}
}
}
__THREAD_END__:
if(tptd)
{
TPTask * task = tptd->task();
if(task)
{
WARNING_MSG(fmt::format("TPThread::threadFunc: task {0:p} not finish, thread.{1:p} will exit.\n",
(void*)task, (void*)tptd));
delete task;
}
tptd->onEnd();
tptd->state_ = THREAD_STATE_END;
tptd->reset_done_tasks();
}
通过TPTask,对象传入
virtual void processTask(TPTask* pTask){ pTask->process(); }
通过查看TPTask的知道主要使用线程池的是dbmagr,也就是负责数据库查询的进程,多线程主要是满足进行数据库查询。
线程的堆栈调用顺序
三、线程池的具体使用
查看另一篇《KBEngine,数据库查询消息流程》https://blog.csdn.net/hu123he/article/details/119790150