带你实现简单线程池

为什么用线程池

1.创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处理效率。

2.线程并发数量过多,抢占系统资源从而导致阻塞。

3.对线程进行一些简单的管理。

使用线程池

1.定义一个基本函数类,用户可继承此类实现自定义方法即可使用。

class ThreadBaseFunc {};//用户继承该类,自定义函数即可使用。

2.定义一个函数指针,为基本类的函数对象。

typedef int (ThreadBaseFunc::* FUNC)();//定义函数对象

3.定义一个仿函数类实现,重写“()”运算符。

class ThreadWorker {//工作函数类
public:
	ThreadWorker() :thiz(NULL), fun(NULL) {}
	ThreadWorker(ThreadBaseFunc* th, FUNC fu) :thiz(th), fun(fu) {}//传入子类指针,多态的实现
	ThreadWorker(const ThreadWorker& worker) {//复制构造
		if (&worker != this) {
			thiz = worker.thiz;
			fun = worker.fun;
		}
	}
	ThreadWorker& operator = (const ThreadWorker& worker) {
		if (&worker != this) {
			thiz = worker.thiz;
			fun = worker.fun;
		}
		return *this;
	}
	int operator() () {//重载函数对象
		if (IsValid()) {
			return (thiz->*fun)();
		}
		return -1;
	}
	bool IsValid() const{//判断工作函数对象是否有效
		return (thiz != NULL) && (fun != NULL);
	}
private:
	ThreadBaseFunc* thiz;//基本对象类
	FUNC fun;//实现的函数
};

4.自定义线程类

class TestThread {//线程类
public:
	TestThread() {
		m_thread = NULL;
		m_bStatus = false;
	}
	~TestThread(){}
	bool Start(){//启动线程函数
		m_bStatus = true;//把线程状态置为true
		m_thread = (HANDLE)_beginthread(&ThreadEntry,0,this);//开启线程
		if (!IsValid()) {//检验线程是否启动成功
			m_bStatus = false;
		}
		return m_bStatus;
	}
	bool Stop(){//停止线程
		if (m_bStatus == false) return false;//判断线程当前状态 false直接返回
		m_bStatus == false;
		DWORD ret = WaitForSingleObject(m_thread, 1000);//等待一秒判断线程是否结束 WAIT_TIMEOUT为正在运行,WAIT_OBJECT_0 为结束
		if (ret == WAIT_TIMEOUT) {
			TerminateThread(m_thread, -1);//终止线程
		}
		UpdateWorker();
		return true;
	}
	void UpdateWorker(const ThreadWorker& worker = ThreadWorker()){//给线程分配任务
		if ((m_worker.load() != NULL)&&(m_worker.load()!=&worker)) {//判断原子对象的存储的值是否为NULL或者为worker
			ThreadWorker* pWorker = m_worker.load();//加载对象
			m_worker.store(NULL);
			delete pWorker;//释放对象
		}
		if (m_worker.load() == &worker) return;//如果是本身,则直接返回
		if (!worker.IsValid()) {//判断函数对象是否有效
			m_worker.store(NULL);
			return;
		}
		m_worker.store(new ThreadWorker(worker));//把新对象存进原子对象,在堆区分配空间
	}
	bool IsValid(){//判断线程是否有有效
		if ((m_thread == NULL) || (m_thread == INVALID_HANDLE_VALUE)) {//为NULL或者为无效句柄
			return false;
		}
		return WaitForSingleObject(m_thread, 0) == WAIT_TIMEOUT;//
	}
	bool IsIdle(){//判断当前线程是否空闲
		if (m_worker.load() == NULL) return true;
		return !m_worker.load()->IsValid();
	}
protected:
	static void ThreadEntry(void* args) {//线程入口函数
		TestThread* thiz = (TestThread*)args;
		thiz->ThreadMain();
		_endthread();
	}

	void ThreadMain() {//线程执行函数
		while (m_bStatus) {//判断线程状态
			if (m_worker.load() == NULL) {//判断现在的函数对象是否有,如果没有则继续循环轮询
				Sleep(1);
				continue;
			}
			ThreadWorker worker = *m_worker.load();
			if (worker.IsValid()) {//判断函数对象是否可用
				if (WaitForSingleObject(m_thread, 0) == WAIT_TIMEOUT) {//判断线程是否正在运行
					int ret = worker();
					if (ret != 0) {//规定函数对象调用本身返回值为0正常执行
						//打印出错结果
					}
					if (ret < 0) {
						m_worker.store(NULL);
					}
				}
			}
			else {
				Sleep(1);
			}
		}
	}
private:
	HANDLE m_thread;//线程句柄
	bool m_bStatus;//线程状态 true表示线程正在执行 false表示线程已经结束
	std::atomic<ThreadWorker*> m_worker;//原子类装载工作函数对象
};

5.定义线程池类

class TestThreadPool {
	TestThreadPool(){}
	TestThreadPool(size_t size) {//初始化线程池,参数为线程个数
		m_threads.resize(size);
		for (size_t i = 0; i < size; i++)
		{
			m_threads[i] = new TestThread();
		}
	}
	~ZSHThreadPool() {
		Stop();//暂停线程池里所有线程
		for (size_t i = 0; i < m_threads.size(); i++)
		{
			delete m_threads[i];
			m_threads[i] = NULL;
		}
		m_threads.clear();//清空队列
	}
	bool Invoke() {//启动线程池
		bool ret = true;
		for (size_t i = 0; i < m_threads.size(); i++)
		{
			if (m_threads[i]->Start() == false) {//所有线程是否启动成功
				ret = false;
				break;
			}
		}
		if (ret == false) {//如果有未启动成功的线程,暂停所有已启动的线程
			for (size_t i = 0; i < m_threads.size(); i++)
			{
				m_threads[i]->Stop();
			}
		}
		return ret;
	}
	void Stop() {//暂停所有线程
		for (size_t i = 0; i < m_threads.size(); i++)
		{
			m_threads[i]->Stop();
		}
	}
	int DispatchWorker(const ThreadWorker& worker) {//分发任务
		int index = -1;
		m_lock.lock();//分发任务加锁,避免出现多个线程同时添加进
		for (size_t i = 0; i < m_threads.size(); i++)
		{
			if (m_threads[i]->IsIdle()) {//判断是否有空闲线程
				m_threads[i]->UpdateWorker(worker);
				index = i;
				break;
			}
		}
		m_lock.unlock();//解锁
		return index;//返回下标
	}
	bool CheckThreadValid(size_t index) {//检查线程是否有效
		if (index < m_threads.size()) return m_threads[index]->IsValid();
		return false;
	}
private:
	std::mutex m_lock;//对分发任务加锁
	std::vector<TestThread*> m_threads;//线程队列
};

6.实现继承基础类。

class TestThread :public ThreadBaseFunc {
public:
    /*....自定义函数*/
    int TestFunc1(){
    }
    int TestFunc2(){
    }
};

7.使用线程池类。

int main(){
    TestThreadPool pool(6);//创建线程池对象
    pool.Invoke();//启动线程池
    ThreadWorker worker1(this, (FUNC)&TestThread::TestFunc1);//创建工作函数对象,调用的是TestFunc1
    pool.DispatchWorker(worker1);//分发任务
    ThreadWorker worker2(this, (FUNC)&TestThread::TestFunc2);//创建工作函数对象,调用的是TestFunc2
    pool.DispatchWorker(worker2);//分发任务
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值