muduo源码分析:线程池类ThreadPool

本文详细分析了muduo库中的线程池实现,包括其核心成员变量如任务队列和线程组,以及关键成员函数如start、stop、take和runInThread。线程池通过条件变量同步任务队列,使用线程执行函数循环获取并执行任务。此外,还提到了相关参考资料,如c++教程网和《Linux多线程服务器端编程》陈硕。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线程池包括

成员变量:

一个任务队列:deque queue_,用条件变量同步

线程组:ptr_vector threads_

bool running :标志是否start启动了,或者stop 停止了

成员函数:

start:初始化线程数目

stop:停止线程池

take:从queue中获取任务

runInThread:线程执行函数 :循环 调用 take 获取任务,并执行任务

#ifndef MUDUO_BASE_THREADPOLL_H
#define MUDUO_BASE_THREADPOLL_H

#include <muduo/base/Condition.h>
#include <muduo/base/Mutex.h>
#include <muduo/base/Thread.h>
#include <muduo/base/Types.h>

#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/ptr_container/ptr_vector.hpp>

#include <deque>

namespace muduo
{

class ThreadPool : boost::noncopyable
{
	public:
		typedef boost::function<void ()> Task;

		explicit ThreadPool(const string& name = string());
		~ThreadPool();

		void start(int numThreads);//启动numThreads个线程
		void stop();//停止线程池

		void run(const Task& f);//将任务f加入线程池运行
	private:
		void runInThread();//线程创建时所传入的运行函数: --> take( )--> f( ) 即运行run中添加的任务f
		Task take();//获取任务队列 queue_ 中的任务 即run中添加的f

		MutexLock mutex_;
		Condition cond_;
		string name_;
		boost::ptr_vector<muduo::Thread> threads_;
		std::deque<Task> queue_;
		bool running_;
};

}
#endif
#include <muduo/base/ThreadPool.h>
#include <muduo/base/Exception.h>

#include <boost/bind.hpp>
#include <assert.h>
#include <stdio.h>

using namespace muduo;

ThreadPool::ThreadPool(const string& name)
		: mutex_(),
		  cond_(mutex_),
		  name_(name),
		  running_(false)
{
}

ThreadPool::~ThreadPool()
{
	if(running_)
	  stop();
}
	
void ThreadPool::start(int numThreads)
{
	//assert(threads_.empty());
	if(!threads_.empty())
		return ;
	running_ = true;
	threads_.reserve(numThreads);
	for(int i=0;i<numThreads;i++)
	{
		char id[32];
		snprintf(id, sizeof id, "%d", i);
		threads_.push_back(new muduo::Thread(boost::bind(&ThreadPool::runInThread, this), name_+id));
		threads_[i].start();
	}
}

void ThreadPool::stop()
{
	{
		MutexLockGuard lock(mutex_);//一定要加锁!!,因为要修改running_,take()里面wait等待的条件里有running,如果不加锁保护running,take()中先执行while判断running为true,接着下面修改了running,也notifyAll了,这时take中才执行wait,那就永远锁住。
		running_ = false;
		cond_.notifyAll();
	}
	for_each(threads_.begin(), threads_.end(), boost::bind(&muduo::Thread::join, _1));//等待线程回收
}

void ThreadPool::run(const Task& task)
{
	if(threads_.empty())
	  task();
	else
	{
		MutexLockGuard lock(mutex_);
		queue_.push_back(task);
		cond_.notify();
	}
}

ThreadPool::Task ThreadPool::take()
{
	MutexLockGuard lock(mutex_);
	//要判断running,如果stop了线程池,那就不要再wait了
	while(queue_.empty() && running_)
	  cond_.wait();
	Task task;//task=0 boost::function 可以判断是否为NULL
	//一定要判断队列非空,因为可能时running为false 退出上面循环的
	if(!queue_.empty())
	{
		task=queue_.front();
		queue_.pop_front();
	}
	return task;
}

void ThreadPool::runInThread()
{
	try
	{
		while(running_)
		{
			Task work=take();//获取任务
			if(work)//要判断任务是否为空,因为stop的时候会返回空task
				work();
		}
	}
	catch(const Exception& ex)
    {
		fprintf(stderr, "exception caught in ThreadPool  %s\n", name_.c_str());
		fprintf(stderr, "reason: %s\n", ex.what());
		fprintf(stderr, "stack trace: %s\n", ex.         stackTrace());
		abort();
	}
    catch (const std::exception& ex) 
    {
		fprintf(stderr, "exception caught in ThreadPool  %s\n", name_.c_str());
		fprintf(stderr, "reason: %s\n", ex.what());
		abort();
	} 
	catch (...)
	{
		fprintf(stderr, "unknown exception caught in     ThreadPool %s\n", name_.c_str());
		throw; // rethrow
	 }
}

参考:c++教程网

           muduo网络库

           linux多线程服务器端编程》.陈硕




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值