muduo源碼分析:線程池類ThreadPool

線程池包括

成員變量:

一個任務隊列: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多線程服務器端編程》.陳碩




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章