目錄
前言
一、線程池介紹
??線程池基本概念
??線程池組成部分
??線程池工作原理?
二、線程池代碼封裝
??main.cpp
??ThreadPool.h
??ThreadPool.cpp
??ChildTask.h?
??ChildTask.cpp
??BaseTask.h
??BaseTask.cpp
三、測(cè)試效果
四、總結(jié)
??創(chuàng)建線程池的好處
前言
本文主要學(xué)習(xí)Linux內(nèi)核編程,結(jié)合Visual Studio 2019進(jìn)行跨平臺(tái)編程,內(nèi)容包括線程池介紹以及線程池封裝
一、線程池介紹
??線程池基本概念
- 線程池是預(yù)先創(chuàng)建線程的一種技術(shù) (服務(wù)器真正意義上實(shí)現(xiàn)高并發(fā)就必須用線程池)
- ??舉個(gè)例子:生活中的水池,是裝東西的容器,用來(lái)裝水的,線程池當(dāng)然就是拿來(lái)裝線程的
- 線程池在任務(wù)還沒(méi)有到來(lái)之前,創(chuàng)建一定數(shù)量的線程,放入空閑隊(duì)列中,這些線程都是處于阻塞狀態(tài),不消耗CPU,但占用較小的內(nèi)存空間
- 當(dāng)新任務(wù)到來(lái)時(shí),緩沖池選擇一個(gè)空閑線程,把任務(wù)傳入此線程中運(yùn)行,如果緩沖池已經(jīng)沒(méi)有空閑線程,則新建若干個(gè)線程,當(dāng)系統(tǒng)比較空閑時(shí),大部分線程都一直處于暫停狀態(tài),線程池自動(dòng)銷(xiāo)毀一部分線程,回收系統(tǒng)資源
??線程池組成部分
- 線程池類(lèi)
????????維護(hù)工作者線程隊(duì)列(包括空閑與忙碌隊(duì)列)
????????維護(hù)一個(gè)任務(wù)隊(duì)列
????????維護(hù)一個(gè)線程池調(diào)度器指針
- 線程池調(diào)度器(本身也是一個(gè)線程)
????????負(fù)責(zé)線程調(diào)度
????????負(fù)責(zé)任務(wù)分配
- 工作者線程類(lèi)(線程池中的線程類(lèi)的封裝)
- 任務(wù)隊(duì)列
- 任務(wù)接口(實(shí)際的業(yè)務(wù)邏輯都繼承自該接口)
??線程池工作原理?
根據(jù)服務(wù)器的需要,來(lái)設(shè)置線程的數(shù)量,可能是10條、20條、30條,根據(jù)服務(wù)器的承載,10條不代表只能做10個(gè)任務(wù),總有任務(wù)做的快,有的做的慢,可能可以完成20個(gè)任務(wù)?
??舉個(gè)例子:如上動(dòng)圖所示,當(dāng)我們服務(wù)器收到一個(gè)注冊(cè)業(yè)務(wù),是一個(gè)服務(wù)器要執(zhí)行的任務(wù),它會(huì)進(jìn)入到任務(wù)隊(duì)列,隊(duì)列先進(jìn)先出,順次執(zhí)行,任務(wù)會(huì)喚醒空閑列表當(dāng)中的一個(gè)空閑的線程,接到任務(wù)之后,空閑線程會(huì)從空閑列表中消失,進(jìn)入到忙碌列表,去完成對(duì)應(yīng)的任務(wù),完成任務(wù)后,從忙碌列表中出去,到空閑列表繼續(xù)等待新任務(wù)
如果,所有的線程都在忙,都在做任務(wù),這時(shí)候登錄進(jìn)來(lái),先進(jìn)入任務(wù)隊(duì)列,會(huì)創(chuàng)建一個(gè)新的線程來(lái)接這個(gè)任務(wù),當(dāng)所有線程都完成任務(wù),回到空閑列表后,新創(chuàng)建的線程銷(xiāo)毀,留下原先設(shè)置的對(duì)應(yīng)數(shù)量線程(類(lèi)似,保留老員工,把實(shí)習(xí)生裁員)
- 隊(duì)列:先進(jìn)先出
- 空閑列表(鏈表):不定長(zhǎng)(有的時(shí)候可能需要?jiǎng)?chuàng)建新線程來(lái)接任務(wù))
- 忙碌列表(鏈表):不定長(zhǎng)(有的時(shí)候可能需要?jiǎng)?chuàng)建新線程來(lái)接任務(wù))
話不多說(shuō),咱們上號(hào),封裝一下線程池相關(guān)函數(shù),來(lái)進(jìn)行測(cè)試?
二、線程池代碼封裝
??main.cpp
- 主函數(shù),設(shè)置10條線程,來(lái)執(zhí)行30個(gè)任務(wù)?
#include <iostream>
#include <stdio.h>
#include "ThreadPool.h"
#include "ChildTask.h"
using namespace std;
int main()
{
ThreadPool* pool = new ThreadPool(10);//10條線程
for (int i = 0; i < 30; i++)//設(shè)置30個(gè)任務(wù)
{
char buf[40] = { 0 };//初始化
sprintf(buf, "%s%d", "任務(wù)", i);
BaseTask* task = new ChildTask(buf);
pool->pushTask(task);
}
while (1) {}
return 0;
}
??ThreadPool.h
- 對(duì)線程池進(jìn)行設(shè)計(jì),核心包括最大、最小線程數(shù),忙碌列表,空閑列表,任務(wù)隊(duì)列,互斥量,條件變量,以及線程執(zhí)行函數(shù)
#pragma once
#include <queue>//隊(duì)列
#include <list>//鏈表頭文件
#include <pthread.h>//線程頭文件
#include <algorithm>//find查找
#include <iostream>
#include "BaseTask.h"
using namespace std;
#define MIN_NUM 10//最小值 默認(rèn)參數(shù)
class ThreadPool
{
public:
ThreadPool(const int num = MIN_NUM);
~ThreadPool();
//判斷任務(wù)隊(duì)列是否為空
bool QueueIsEmpty();
//線程互斥量加鎖解鎖
void Lock();
void Unlock();
//線程條件變量等待和喚醒
void Wait();
void WakeUp();
//添加任務(wù)到任務(wù)隊(duì)列
void pushTask(BaseTask* task);
//從任務(wù)隊(duì)列移除任務(wù)
BaseTask* popTask(BaseTask* task);
//從忙碌回到空閑 工作結(jié)束
void MoveToIdle(pthread_t id);
//從空閑到忙碌 工作開(kāi)始
void MoveToBusy(pthread_t id);
//線程執(zhí)行函數(shù)
static void* RunTime(void* vo);
private:
int threadMinNum;//最大線程數(shù)量
int threadMaxNum;//最小線程數(shù)量
queue<BaseTask*>taskQueue;//任務(wù)隊(duì)列
list<pthread_t>busyList;//線程忙碌列表
list<pthread_t>idleList;//線程空閑列表
pthread_mutex_t mutex;//互斥量:做鎖
pthread_cond_t cond;//條件變量:讓線程等待或者喚醒
};
??ThreadPool.cpp
- 對(duì)函數(shù)進(jìn)行參數(shù)的設(shè)置,核心在于線程執(zhí)行函數(shù)上的設(shè)置,在工作前和工作完設(shè)置打印,方便我們進(jìn)行觀察
#include "ThreadPool.h"
ThreadPool::ThreadPool(const int num)
{
this->threadMinNum = num;
//條件變量、互斥量初始化
pthread_mutex_init(&this->mutex, NULL);
pthread_cond_init(&this->cond, NULL);
pthread_t id;
//線程num條創(chuàng)建
for (int i = 0; i < this->threadMinNum; i++)
{
//線程創(chuàng)建
pthread_create(&id, NULL, RunTime, this);
this->idleList.push_back(id);//線程存入空閑列表
}
}
ThreadPool::~ThreadPool()
{
}
//任務(wù)隊(duì)列是否為空
bool ThreadPool::QueueIsEmpty()
{
return this->taskQueue.empty();
}
//線程加鎖
void ThreadPool::Lock()
{
pthread_mutex_lock(&this->mutex);
}
//線程解鎖
void ThreadPool::Unlock()
{
pthread_mutex_unlock(&this->mutex);
}
//線程等待
void ThreadPool::Wait()
{
pthread_cond_wait(&this->cond, &this->mutex);
}
//線程喚醒
void ThreadPool::WakeUp()
{
pthread_cond_signal(&this->cond);
}
//添加任務(wù)到任務(wù)隊(duì)列
void ThreadPool::pushTask(BaseTask* task)
{
Lock();
taskQueue.push(task);
Unlock();
WakeUp();
}
//從任務(wù)隊(duì)列移除任務(wù)
BaseTask* ThreadPool::popTask(BaseTask* task)
{
task = this->taskQueue.front();//從隊(duì)列頭取
this->taskQueue.pop();//刪除隊(duì)列頭
return task;
}
//從忙碌回到空閑 工作結(jié)束
void ThreadPool::MoveToIdle(pthread_t id)
{
list<pthread_t>::iterator iter;
iter = find(busyList.begin(), busyList.end(), id);
if (iter != busyList.end())
{
//從忙碌移除
this->busyList.erase(iter);
//添加到空閑
this->idleList.push_back(*iter);//this->idleList.push_back(id)
}
}
//從空閑到忙碌 工作開(kāi)始
void ThreadPool::MoveToBusy(pthread_t id)
{
list<pthread_t>::iterator iter;
iter = find(idleList.begin(), idleList.end(), id);
if (iter != idleList.end())
{
//從空閑移除
this->idleList.erase(iter);
//添加到忙碌
this->busyList.push_back(*iter);//this->idleList.push_back(id)
}
}
//線程執(zhí)行函數(shù)
void* ThreadPool::RunTime(void* vo)
{
//拿到執(zhí)行線程自己的id 因?yàn)楹竺嬉幚砻β岛涂臻e的情況
pthread_t id = pthread_self();
//確保主線程與子線程分離,子線程結(jié)束后,資源自動(dòng)回收
pthread_detach(id);
//線程參數(shù)獲取
ThreadPool* argThis = (ThreadPool*)vo;
while (true)
{
argThis->Lock();
//如果任務(wù)隊(duì)列為空 線程則一直等待
//知道任務(wù)隊(duì)列不為空則會(huì)被pushTask函數(shù)喚醒線程
while (argThis->QueueIsEmpty())
{
argThis->Wait();
}
argThis->MoveToBusy(id);
cout << "工作前 任務(wù)數(shù):" << argThis->taskQueue.size() << endl;
cout << "工作前 busy:" << argThis->busyList.size() << endl;
cout << "工作前 idle:" << argThis->idleList.size() << endl;
cout << "-----------------------------------------------" << endl;
//取任務(wù)
BaseTask* task;
task = argThis->popTask(task);
argThis->Unlock();
//任務(wù)工作
task->working();
//工作結(jié)束
argThis->Lock();
argThis->MoveToIdle(id);
argThis->Unlock();
cout << "工作完 任務(wù)數(shù):" << argThis->taskQueue.size() << endl;
cout << "工作完 busy:" << argThis->busyList.size() << endl;
cout << "工作完 idle:" << argThis->idleList.size() << endl;
cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl;
}
return nullptr;
}
??ChildTask.h?
- 子類(lèi)配置?
#pragma once
#include "BaseTask.h"
#include <iostream>
#include <unistd.h>//sleep頭文件
using namespace std;
class ChildTask :
public BaseTask
{
public:
ChildTask(char* data);
~ChildTask();
void working();
};
??ChildTask.cpp
- 子類(lèi)設(shè)置延時(shí)模擬做任務(wù)的時(shí)間比較長(zhǎng)?
#include "ChildTask.h"
ChildTask::ChildTask(char* data) :BaseTask(data)//參數(shù)傳給父類(lèi)
{
}
ChildTask::~ChildTask()
{
}
void ChildTask::working()
{
cout << this->data << "正在執(zhí)行......" << endl;
sleep(3);//延時(shí)3秒 (模擬做業(yè)務(wù)的時(shí)間比較長(zhǎng))
}
??BaseTask.h
- 基類(lèi)設(shè)置結(jié)構(gòu)體來(lái)裝業(yè)務(wù)?
#pragma once
#include <string.h>
class BaseTask
{
public:
BaseTask(char* data);
~BaseTask();
char data[1024]; //裝業(yè)務(wù)
virtual void working() = 0;//虛函數(shù)
};
??BaseTask.cpp
- 基類(lèi)配置?
#include "BaseTask.h"
BaseTask::BaseTask(char* data)
{
bzero(this->data, sizeof(this->data));//清空
memcpy(this->data, data, sizeof(data));
}
BaseTask::~BaseTask()
{
delete this->data;//清除釋放
}
三、測(cè)試效果
- 通過(guò)Linux連接VS進(jìn)行跨平臺(tái)編程,我們可以清晰的看到有幾個(gè)線程是在做任務(wù),幾個(gè)線程是空閑的,整個(gè)過(guò)程就很清晰直觀的展現(xiàn)出來(lái)了,如下動(dòng)圖所示:?
- 10條線程做30個(gè)任務(wù)的全部記錄,如下如所示:
四、總結(jié)
??創(chuàng)建線程池的好處
- 線程池的使用,能讓我們搭建的高并發(fā)服務(wù)器真正意義上做到高并發(fā)
- 降低資源消耗
????????通過(guò)重復(fù)利用自己創(chuàng)建的線程降低線程創(chuàng)建和銷(xiāo)毀造成的消耗
- 提高響應(yīng)速度
????????當(dāng)任務(wù)到達(dá)時(shí),任務(wù)可以不需要等待線程創(chuàng)建和銷(xiāo)毀就能立即執(zhí)行
- 提高線程的可管理性
????????線程式稀缺資源,如果無(wú)限的創(chuàng)建線程,不僅會(huì)消耗資源,還會(huì)降低系統(tǒng)的穩(wěn)定性
????????使用線程池可以進(jìn)行統(tǒng)一分配,調(diào)優(yōu)和監(jiān)控
以上就是本文的全部?jī)?nèi)容啦!如果對(duì)您有幫助,麻煩點(diǎn)贊啦!收藏啦!歡迎各位評(píng)論區(qū)留言?。。?/strong>文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-793425.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-793425.html
到了這里,關(guān)于【Linux網(wǎng)絡(luò)編程】高并發(fā)服務(wù)器框架 線程池介紹+線程池封裝的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!