【线程池封装】实现简单回射服务器


图.1 线程池框架
半同步/半反应堆模式(半同步/半异步模式的变体)
类封装:
template<typename T>
class ThreadPool
{

public:
	ThreadPool(int threadnum = 8, int maxreqnum = 1000);
	~ThreadPool()
	{
		delete [] m_Pthread;
		m_Stop = true;
	}
	/* 往队列添加任务 */
	bool Append(T *request);

	/*	线程函数不能执行对象成员函数,所以声明为static,此时函数不能使用对象非静态成员,故将访问的工作交给Run函数,
	*   this 传递到args。(Work应该封装到类里面)——Singleton模式 
	*/
	static void* Work(void *args);
	void Run(int index);

private:
	/* 请求队列最大任务数 */
	int m_MaxRequestNum;
	/* 线程池线程数量 */
	int m_ThreadNum;

	pthread_t *m_Pthread;
	/* 线程是否应该结束 */
	bool m_Stop;

	/* 子线程在等待任务时,应该进入睡眠,用信号量;而资源竞争(获取队列中的一个任务)用互斥量保护 */
	pthread_mutex_t m_QueMutex;
	sem_t m_QueSem;

	/* 任务列表 */
	std::list<T *> m_WorkList;
};

创建并分离线程:
template<typename T>		
ThreadPool<T>::ThreadPool(int threadnum, int maxreqnum)
	: m_MaxRequestNum(maxreqnum), m_ThreadNum(threadnum), m_Pthread(nullptr), m_Stop(false)
{
	int ret;
	/* 信号量值小于零就block */
	ret = sem_init(&m_QueSem, 0, 0);
	if (ret == -1)
	{
		printf("ThreadPool: [sem_init] failed, errno[%d]:%s\n", errno, strerror(errno));
		exit(-1);
	}
	m_QueMutex = PTHREAD_MUTEX_INITIALIZER;

	if (!m_Pthread)
	{
		m_Pthread = (pthread_t *)malloc(sizeof(pthread_t) * m_ThreadNum);
		/* 如果分配失败,应该退出 */
		if (!m_Pthread)
		{
			printf("ThreadPool: [malloc] failed, errno[%d]:%s\n", errno, strerror(errno));
			exit(-1);
		}
	}

	for (int i = 0; i < threadnum; ++i)
	{
		/* 将this指针传递给static成员函数,实现Singleton模式 */
		ret = pthread_create(m_Pthread + i, nullptr, Work, this);
		if (ret != 0)
		{
			delete [] m_Pthread;
			printf("ThreadPool: [pthread_create] failed, errno[%d]:%s\n", ret, strerror(ret));
			exit(-1);
		}
		/* 分离线程,子线程马上到执行区等待任务 */
		ret = pthread_detach(m_Pthread[i]);
		if (ret != 0)
		{
			delete [] m_Pthread;
			printf("ThreadPool: [pthread_detach] failed, errno[%d]:%s\n", ret, strerror(ret));
			exit(-1);			
		}
	}
}

从任务列表获取任务,互斥量用于防止多个线程共同使用一个变量,而信号量避免的由于pthread_mutex_lock带来的cpu消耗,让线程进入睡眠状态:

template<typename T>
void* ThreadPool<T>::Work(void *args)
{
    static int index = 0;
    index++;
    ThreadPool<T> *pthreadpool = (ThreadPool<T> *)args;
    pthreadpool->Run(index);
    return nullptr;
}

template<typename T>
void ThreadPool<T>::Run(int index)
{
	printf("pthread:%d\n", index);
	while (!m_Stop)
	{

		sem_wait(&m_QueSem);
		printf("pthread:%d\n", index);
		pthread_mutex_lock(&m_QueMutex);
		
		if (m_WorkList.empty())
		{
			pthread_mutex_unlock(&m_QueMutex);
			continue;
		}
		/* 获取一个任务 */
		T* request = m_WorkList.front();
		m_WorkList.pop_front();

		pthread_mutex_unlock(&m_QueMutex);
		if (!request)
		{
			continue;
		}
		request->Process();
		delete request;
	}
}

添加任务到任务列表,并发出有新任务到来的信号:
template<typename T>
bool ThreadPool<T>::Append(T *request)
{
	pthread_mutex_lock(&m_QueMutex);
	
	if (m_WorkList.size() > m_MaxRequestNum)
	{
		pthread_mutex_unlock(&m_QueMutex);
		printf("ThreadPool: [Append] failed, Client sum is over m_MaxRequestNum \n");
		return false;
	}
	m_WorkList.push_back(request);

	pthread_mutex_unlock(&m_QueMutex);
	sem_post(&m_QueSem);
	return true;
}


源码见 Github: https://github.com/jammgit/ThreadPool


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值