c++学习——线程池

c++学习——线程池

线程池的组成主要分为 3 个部分,这三部分配合工作就可以得到一个完整的线程池:

  • 任务队列,存储需要处理的任务,由工作的线程来处理这些任务
    • 通过线程池提供的 API 函数,将一个待处理的任务添加到任务队列,或者从任务队列中删除
  • 工作的线程(任务队列任务的消费者) ,N个
    • 线程池中维护了一定数量的工作线程,他们的作用是是不停的读任务队列,从里边取出任务并处理
    • 工作的线程相当于是任务队列的消费者角色,
    • 如果任务队列为空,工作的线程将会被阻塞 (使用条件变量 / 信号量阻塞)。如果阻塞之后有了新的任务,由生产者将阻塞解除,工作线程开始工作
  • 管理者线程(不处理任务队列中的任务),1个
    • 它的任务是周期性的对任务队列中的任务数量以及处于忙状态的工作线程个数进行检测
    • 当任务过多的时候,可以适当的创建一些新的工作线程
    • 当任务过少的时候,可以适当的销毁一些工作的线程

任务类

class Task { // 任务类
public: 
	typedef void (*TaskCallBack)(void*);
	void setTaskCallBack(TaskCallBack mb, void* arg) { this->mTaskCallBack = mb; this->args = arg; } // 设置任务及参数
	// 句柄
	void handle(){
		if (this->mTaskCallBack) { this->mTaskCallBack(this->args); }
	}
	// 等值构造函数
	void operator=(const Task& t) { this->args = t.args; this->mTaskCallBack = t.mTaskCallBack; }
	//~Task() { delete args; args = nullptr; }
private:
	void* args; // 回调函数参数
	TaskCallBack mTaskCallBack; // 回调函数
};

任务队列

class TaskQueue { // 任务队列
public:
	typedef void (*TaskCallBack)(void*);
	void addTask(TaskCallBack tb, void* arg); // 添加任务
	void addTask(Task task); // 添加任务
	Task getTask(); // 取出一个任务
	int getTaskNum() { 
		unique_lock<mutex> sb(task_mutex);
		int x = mtaskqueue.size();
		sb.unlock();
		return x;
	}
private:
	queue<Task> mtaskqueue; // 任务队列
	mutex task_mutex;
};


void TaskQueue::addTask(Task task) {
	unique_lock<mutex> sb(task_mutex);
	mtaskqueue.push(task);
}

void TaskQueue::addTask(TaskCallBack tb, void* arg) {
	Task t;
	t.setTaskCallBack(tb, arg);
	unique_lock<mutex> sb(task_mutex);
	mtaskqueue.push(t);
}

Task TaskQueue::getTask() {
	Task t;
	if (!mtaskqueue.empty()) {
		task_mutex.lock();
		if (!mtaskqueue.empty()) {
			t = mtaskqueue.front();
			mtaskqueue.pop();
		}
		task_mutex.unlock();
	}
	return t;
}

线程类


class Thread { // 自定义线程类
public:
	bool start(void* arg);
	bool detach();
	bool join();
	thread::id id;
	Thread() :mArg(nullptr), mIsStart(false), mIsDetach(false) {};
	~Thread();
private:
	virtual void run(void* arg) = 0;
	void* threadRun(void*);
	void* mArg;
	bool mIsStart;
	bool mIsDetach;
	thread mThreadId;
};


bool Thread::start(void* arg)
{
	mArg = arg;
	mThreadId = thread(&Thread::threadRun, this, this);
	mIsStart = true;
	id = mThreadId.get_id();
	return true;
}

bool Thread::detach()
{
	if (!mIsStart) { return false; }
	if (mIsDetach) { return true; }
	mThreadId.detach();
	mIsDetach = true;
	return true;
}

bool Thread::join()
{
	if (!mIsStart || mIsDetach) { return false; }
	mThreadId.join();
	return true;
}

Thread::~Thread()
{
	if (mIsStart && !mIsDetach) { detach(); }
}

void* Thread::threadRun(void* arg)
{
	Thread* t = (Thread*) arg;
	t->run(t->mArg);
	return nullptr;
}

线程池

class ThreadPool { // 线程池类
public:
	typedef void (*TaskCallBack)(void*);
	explicit ThreadPool(int minTr, int maxTr);
	~ThreadPool();
	void addTask(Task task); // 添加任务
	void addTask(TaskCallBack tb, void* arg); // 添加任务
	int getBusyThreadNum(); // 获取忙线程数
	int getLiveThreadNum(); // 获取存在的线程数
	int getTaskNum(); // 获取任务数
private:
	class MWorkThread : public Thread {
	protected:
		virtual void run(void* arg);
	};
	class MManaThread : public Thread {
	protected:
		virtual void run(void* arg);
	};
	void ThreadsExit(thread::id mid); // 退出线程
	void workerloop(); // worker的回调
	void managerloop(); // manager的回调
	void startmanager(); // 开始manager线程
	void createThreads(int n, int livenum); // 创建线程
	
	int minThreadNum; // 最小线程数
	int maxThreadNum; // 最大线程数
	int busyThreadNum; // 忙线程数
	int liveThreadNum; // 存活线程数
	int exitThreadNum; // 要销毁的线程数
	TaskQueue my_taskQueue; // 任务队列
	mutex mmutex;
	condition_variable mCon; 
	vector<MWorkThread*> mThreads; // 工作线程容器
	MManaThread mManagerThr; // 管理者线程
	bool mQuit; // 线程池退出标志
};


ThreadPool::ThreadPool(int minTr, int maxTr)
{
	mQuit = false;
	minThreadNum = minTr;
	maxThreadNum = maxTr;
	busyThreadNum = 0;
	exitThreadNum = 0;
	liveThreadNum = minTr;
	createThreads(minTr, 0);
	startmanager();
}

ThreadPool::~ThreadPool()
{
	unique_lock<mutex> sb(mmutex);
	mQuit = true;
	mCon.notify_all(); // 通知所有线程退出
}

int ThreadPool::getBusyThreadNum() {
	int b = 0;
	mmutex.lock();
	b = busyThreadNum;
	mmutex.unlock();
	return b;
}

int ThreadPool::getLiveThreadNum() {
	int l = 0;
	mmutex.lock();
	l = liveThreadNum;
	mmutex.unlock();
	return l;
}

int ThreadPool::getTaskNum() {
	return my_taskQueue.getTaskNum();
}

void ThreadPool::ThreadsExit(thread::id mid) {
	for (auto m = mThreads.begin(); m != mThreads.end(); m++) {
		if ((*m)->id == mid) {
			mThreads.erase(m);
			break;
		}
	}
	return;
}

void ThreadPool::workerloop()
{
	while (true)
	{
		unique_lock<mutex> sb(mmutex);
		while (my_taskQueue.getTaskNum() == 0 && !mQuit) {
			cout << "thread " << this_thread::get_id() << " is waiting ... \n";
			mCon.wait(sb, [&](){
				if (my_taskQueue.getTaskNum()!=0 || exitThreadNum > 0) return true;
				return false;
			});
			if (exitThreadNum > 0) {
				exitThreadNum--;
				if (liveThreadNum > minThreadNum) {
					ThreadsExit(this_thread::get_id()); // 退出线程
					liveThreadNum--;
					sb.unlock();
					return; // 结束worker
				}
			}
		}

		if (mQuit) { 
			sb.unlock();
			ThreadsExit(this_thread::get_id());
			return; // 结束worker
		}

		Task task = my_taskQueue.getTask();
		busyThreadNum++;
		sb.unlock();

		cout << "thread " << this_thread::get_id() << " is doing ... \n";
		task.handle();
		cout << "thread " << this_thread::get_id() << " is finish ... \n";
		
		sb.lock();
		busyThreadNum--;
		sb.unlock();
	}
}


void ThreadPool::addTask(Task task) {
	my_taskQueue.addTask(task);
	mCon.notify_one(); // 添加任务同时通知线程
}

void ThreadPool::addTask(TaskCallBack tb, void* arg)
{
	my_taskQueue.addTask(tb, arg);
	mCon.notify_one(); // 添加任务同时通知线程
}


void ThreadPool::createThreads(int n, int livenum) { // 初始化工作线程vector
	for (int i = livenum; i < livenum + n; i++) {
		mThreads.push_back(new MWorkThread());
		mThreads[i]->start(this);
	}
}

void ThreadPool::MWorkThread::run(void* arg) {
	ThreadPool* tp = (ThreadPool*)arg;
	tp->workerloop();
}

void ThreadPool::startmanager() { // 开启管理者线程
	mManagerThr.start(this);
}

void ThreadPool::MManaThread::run(void* arg) {
	ThreadPool* tp = (ThreadPool*)arg;
	tp->managerloop();
}

void ThreadPool::managerloop() {
	while (!mQuit)
	{
		// 每隔1s检测一次
		Sleep(1000);
		// 取出线程池中的任务数和线程数量
		//  取出工作的线程池数量
		unique_lock<mutex> sb(mmutex);
		int queueSize = my_taskQueue.getTaskNum();
		int liveNum = liveThreadNum;
		int busyNum = busyThreadNum;
		sb.unlock();
		
		// 创建线程, 一次创建2个
		const int NUMBER = 2;
		// 当前任务个数>存活的线程数 && 存活的线程数<最大线程个数
		if (queueSize > liveNum && liveNum < maxThreadNum) {
			sb.lock();
			int num = 0;
			for (int i = liveNum; i < maxThreadNum && num < NUMBER && liveThreadNum < maxThreadNum; i++) {
				createThreads(1, liveThreadNum);
				num++;
				liveThreadNum++;
			}
			sb.unlock();
		}

		// 销毁多余的线程
		// 忙线程*2 < 存活的线程数目 && 存活的线程数 > 最小线程数量
		if (busyNum * 2 < liveNum && liveNum > minThreadNum) {
			printf("Begin to exit Thread\n");
			sb.lock();
			exitThreadNum = NUMBER;
			sb.unlock();
			for (int i = 0; i < NUMBER; ++i)
            {
				mCon.notify_one();
            }
		}
	}
}

主函数

typedef void (*TaskCallBack)(void*);
void* MyThreadFunc(void* param)
{
    cout << "param = " << *(int*)param << "\t Thread id = " << this_thread::get_id() << endl;
    Sleep(100);
    return nullptr;
}

int main()
{
    
    ThreadPool p(1, 10);
    int* num = (int*)malloc(sizeof(int));
    if (num == NULL) { return -1; }
    for (int i = 1; i < 500; i++)
    {
        *num = i + 1;
        Task t;
        t.setTaskCallBack((TaskCallBack)MyThreadFunc, num);
        p.addTask(t);
        cout << "Task Num: " << p.getTaskNum() << endl;
        cout << "Busy Thread Num: " << p.getBusyThreadNum() <<endl;
        cout << "Live Thread Num: " << p.getLiveThreadNum() << endl;
        Sleep(100);
    }

    while (true)
    {
        cout << "==================================================\n";
        cout << "Task Num: " << p.getTaskNum() << endl;
        cout << "Busy Thread Num: " << p.getBusyThreadNum() << endl;
        cout << "Live Thread Num: " << p.getLiveThreadNum() << endl;
        Sleep(100);
    }

    return 0;
}

参考:https://subingwen.cn/linux/threadpool/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Y (O - O) Y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值