C++11 实现简单线程池

C++11实现简单线程池

简介

线程池:一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。 例如,线程数一般取cpu数量+2比较合适,线程数过多会导致额外的线程切换开销。

线程池的组成

  1. 线程池: 管理所有线程;
  2. 工作线程: 线程池中的线程,从任务队列中获取任务并执行任务;
  3. 任务队列: 存放需要执行的任务,本文采用deque队列可以存放优先任务;
  4. 添加任务接口: 用于向任务队列中添加任务;

工作原理

首先创建一定数量的线程并处于空闲状态,通过添加任务接口向任务队列添加任务并通知线程去执行,线程收到通知后从任务队列取出任务并执行,当前任务执行完后若任务队列中还有任务则继续取出并执行,否则就进入空闲等待状态。当线程池收到停止信号时等待正在执行的线程执行完成并放弃其余任务。

上代码前先简单介绍deque容器:
deque: 两端支持高效插入和删除容器的元素,是一种具有队列和栈的性质的数据结构,尽管双端队列看起来似乎比栈和队列更灵活,但实际上在应用程序中远不及栈和队列有用,如图:
在这里插入图片描述

代码

threadPool.h

#pragma once
#include <iostream>
#include <vector>
#include <mutex>
#include <deque>
#include <atomic>

using namespace std;

using Task = function<void()>;

class threadPool
{
public:
	threadPool(int nThreadNum = 3);
	~threadPool();

private:
	vector<thread>     m_vThreads;//线程池
	deque<Task>        m_Tasks;//任务队列,采用deque双端队列
	condition_variable m_condVar;//条件变量
	mutex              m_mutex;
	atomic<bool>       m_bStop;//线程池结束标志

protected:
	//工作线程
	void workThread();

public:
	//添加任务
	template<class T, class... Args> void postTask(T t, Args... args)
	{
		if (!m_bStop)
		{
		    //std::move,std::forward 将数据挪用于自身,避免临时变量创建和销毁带来的性能消耗
			auto task = std::bind(std::forward<T>(t), std::forward<Args>(args)...);
			{
				unique_lock<mutex> lck(m_mutex);
				m_Tasks.push_front([task]() {task(); });
			}
			m_condVar.notify_one();
		}
	}
	//添加高优先级任务
	template<class T, class... Args> void sendTask(T t, Args... args)
	{
		if (!m_bStop)
		{
			auto task = std::bind(std::forward<T>(t), std::forward<Args>(args)...);
			{
				unique_lock<mutex> lck(m_mutex);
				m_Tasks.push_back([task]() {task(); });
			}
			m_condVar.notify_one();
		}
	}
	//停止
	void stop();
};


threadPool.cpp

#include "threadPool.h"


threadPool::threadPool(int nThreadNum):m_bStop(false)
{
	int num = nThreadNum <= 0 ? 1 : nThreadNum;
	for (int i=0;i<num;i++)
		m_vThreads.push_back(thread(&threadPool::workThread,this));
}


threadPool::~threadPool()
{
	stop();
}

void threadPool::stop()
{
	if (!m_bStop)
	{
		m_bStop = true;
		m_condVar.notify_all();//唤醒所有线程
		for (auto it = m_vThreads.begin(); it != m_vThreads.end(); it++)
		{
			if (it->joinable())
				it->join();
		}
		m_vThreads.clear();
	}
}

void threadPool::workThread()
{
	cout << "thread: " << this_thread::get_id() <<"  start"<< endl;
	while (!m_bStop)
	{
		Task task;
		{
			unique_lock<mutex> lck(m_mutex);
			m_condVar.wait(lck, [this]() {return m_bStop.load() || !m_Tasks.empty(); });
			if (m_bStop)
				break;
			else
			{
				
				task = move(m_Tasks.back());//获取第一个任务
				m_Tasks.pop_back();//删除任务
			}
		}
		cout << "thread: " << this_thread::get_id() << "  work "<<endl;
		task();//执行任务
	}
	cout << "thread: " << this_thread::get_id() << "  end" << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值