C++11 线程池实现

概述

1、一个线程 pool,所有线程阻塞等待唤醒(有任务时唤醒)
2、任务队列 queue,队列中添加任务后就唤醒线程,线程从队头取走任务执行,典型的生产者-消费者模型。
3、mutex对队列上锁, 保证队列任务添加和取走的同步性
4、当线程数不足时可以动态增加线程数量。

代码

threadpool.hpp头文件

#pragma once
#include <iostream>
#include<stdlib.h>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<vector>
#include<functional>
#include<queue>
#include<atomic>
#define N 10    //默认初始化线程数量
#define THREADPOOL_MAX_NUM  500   //最大线程数量
using namespace std;
class ThreadPool {

public:
	//自定义void()的函数类型
	using Task = function<void()>;

	size_t initnum;
	//线程数组
	vector<thread> _pool;

	//任务队列
	queue<Task> _tasks;

	//互斥锁条件变量
	mutex _mutex;
	condition_variable _cond;

	//线程池是否在工作
	atomic<bool> _run;
	//空闲线程数量
	atomic<int>  _idlThreadNum;
public:
	ThreadPool(int cnt = N) :_run(true), _idlThreadNum(cnt)
	{
		addThread(cnt);  //初始化线程池,线程池数量为cnt
	}
	~ThreadPool()
	{
		_run = false;
		_cond.notify_all(); // 唤醒所有线程执行
		for (thread& thrd : _pool) {
			//thread.detach(); // 让线程“自生自灭”
			if (thrd.joinable())    //线程还在执行任务中则等待
				thrd.join(); // 等待任务结束, 前提:线程一定会执行完			
		}
	}

public:
	//向任务队列添加任务
	void addTask(const Task& f)
	{
		if (_run) {
			//保护共享资源    
			unique_lock<mutex>lk(_mutex);

			//给队列中添加任务
			_tasks.push(f);
			cout << "---------Add a task---------" << endl;
			//空闲线程不够时,增加线程
			if (_idlThreadNum < 1 && _pool.size() < THREADPOOL_MAX_NUM)
			{
				addThread(1);
				cout << "new thread" << endl;
			}

			//唤醒等待线程
			_cond.notify_one();
		}
	}
	//向线程池中增加线程
	void addThread(int num)
	{
		for (; num > 0 && _pool.size() < THREADPOOL_MAX_NUM; num--) {
			_pool.emplace_back(&ThreadPool::runTask, this);    //emplace_back容器内部原地构造
		}
	}
	void runTask()
	{
		//不断遍历队列,判断要是有任务的话,就执行
		while (_run) {

			Task task; // 获取一个待执行的 task
			{
				// unique_lock 相比 lock_guard 的好处是:可以随时 unlock() 和 lock()
				unique_lock<mutex> lock(_mutex);
				_cond.wait(lock, [this] {
					return !_run || !_tasks.empty();   //会暂时解锁lock并等待唤醒
					}); // wait 直到有 task
				if (!_run && _tasks.empty())
					return;
				task = move(_tasks.front()); // 按先进先出从队列取一个 task
				_tasks.pop();
			}
			_idlThreadNum--;
			task();//执行任务
			_idlThreadNum++;
		}
	}
};

测试程序

#include<iostream>
#include"threadpool.hpp"
using namespace std;


void func(int i) {
	cout << "pthread_id=" << this_thread::get_id() << endl;
	cout << "task id" << "------>" << i << endl;
	this_thread::sleep_for(chrono::seconds(rand() % 5));    //模拟工作时长
}
int main()
{
	srand(time(nullptr));
	ThreadPool p(5);
	int i = 0;
	int num = 20;
	while (num--) {
		i++;
		//调整线程之间cpu调度
		this_thread::sleep_for(chrono::milliseconds(100));
		auto task = bind(func, i);
		p.addTask(task);
	}
	return 0;
}

测试结果:
在这里插入图片描述

  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值