Simple Thread Pool Implementation Using C++

Simple Thread Pool Implementation Using C++

1 背景

在多任务系统中,我们经常会通过多进程或多线程去协同完成一个任务,或重复完成相同逻辑的不同任务,对并发及实时响应又有较高要求,一般的方法时,我们当接收到一个任务请求后,创建线程,线程函数完成任务,线程退出,频繁的创建线程会增加系统的负担,不利于线统的性能,且不利于任务的扩展,对系统的负载不可控,所以我们通过线程池来解决上述问题,在系统启动时根据配置(通过系统负载能力预估配置)创建一定数量的线程,由线程池控制块统一管理,在系统退出时,统一销毁线程池和线程,线程池中的线程,通过读取任务队列,去执行任务,完成任务后,线程释放回池中,准备执行下一个任务。
##2 需求 ##

  • 线程池在系统启动后创建,池中线程可通过配置文件修改,修改线程数后,重启系统生效。
  • 线程池生命同期与系统相同,可并发的访问任务队列。
  • 任务队列可以有多条,可按优先级划分队列,最多的8条任务队列,4个优先级。
  • 任务队列中任务需包含三个原素,任务执行函数,任务输入参数,任务状态。
  • 任务队列个数,队列深度,可配置,修改配置后,重启服务后生效。

3 设计

这里写图片描述

4 实现

interface IWorkerItem
{
	/*增加引用*/
	virtual unsigned long AddRef()=0;
	/*减少引用*/
	virtual unsigned long Release()=0;
	/*任务处理函数*/
	virtual void WorkerMain(void* pThis)=0;
};
#ifndef _WORK_ITEM_QUEUE_H_
#define _WORK_ITEM_QUEUE_H_

#include <queue>
#include <list>
#include "IWorkerItem.h"

using namespace std;

/*任务队列类型*/
typedef queue< IWorkerItem,list<IWorkerItem*> > WORKER_ITEM_QUEUE;

class WorkItemQueue
{
public:
	WorkItemQueue();
	~WorkItemQueue(void);
public:
	/*增加任务到队列*/
	bool PutItem(IWorkerItem* _iWork);
	/*获取队列中任务*/
	IWorkerItem* GetItem();
	/*移除队列中任务*/
	bool RemoveItem(IWorkerItem* _iWork);
	/*清除队列中任务项*/
	bool ClearItem();
	/*获取队列大小*/
	int GetWorkerQueueSize();
	/*设置队列的大小*/
	bool SetWorkerQueueSize(int nSize);
	/*获取对列中的任务数*/
	int GetWorkerItemCount();
	/*设置队列中的任务数*/
	bool SetQueueItemCount(int nSize);
public:

private:
	/*任务队列*/
	WORKER_ITEM_QUEUE worker_queue;
	/*队列大小*/
	int nQueSize;
	/*队列中任务数*/
	int nCount;

};


#include <stdio.h>
#include "WorkItemQueue.h"

WorkItemQueue::WorkItemQueue() :nCount(0),nQueSize(0)
{
}

WorkItemQueue::~WorkItemQueue(void)
{
}

bool WorkItemQueue::PutItem(IWorkerItem* _iWork)
{
	if((worker_queue.size()>=nQueSize)||(!_iWork))
	{
		printf("the queue size is exceed expected......\n");
		return false;
	}
	worker_queue.push(_iWork);
	nCount++;
	printf("the item is sucessed add into the queue  cout:%d iWork:%ld\n",nCount,_iWork);
	return true;
}

IWorkerItem* WorkItemQueue::GetItem()
{
	if(!worker_queue.empty())
	{
		IWorkerItem* iwork=worker_queue.front();
		worker_queue.pop();
		nCount--;
		printf("the item is sucessed pop the item cout:%d pWork:%ld \n",nCount,iwork);
		return iwork;
	}	
	printf("the queue is empty......\n");
	return NULL;
}

bool WorkItemQueue::RemoveItem(IWorkerItem* _iWork)
{
	printf("the WorkItemQueue::RemoveItem hv call......\n");
	nCount=0;
	return true;
	
}

bool WorkItemQueue::ClearItem()
{
	/*清空队列中的元素,由于放的是指针,
	需要一个一个的完成释放*/
	nCount=0;
	printf("the WorkItemQueue::ClearItem hv call......\n");

	return true;
}

int WorkItemQueue::GetWorkerQueueSize()
{
	printf("the WorkItemQueue::GetWorkerQueueSize hv call......\n");

	return nQueSize;
}

bool WorkItemQueue::SetWorkerQueueSize(int nSize)
{
	printf("the WorkItemQueue::SetWorkerQueueSize hv call......\n");

	nQueSize=nSize;
	return true;
}

int WorkItemQueue::GetWorkerItemCount()
{
	return nCount;
}

bool WorkItemQueue::SetQueueItemCount(int nSize)
{
	nCount=nSize;
	return true;
}

#ifndef _TTS_THREAD_POOL_H_
#define _TTS_THREAD_POOL_H_

#include <pthread.h>
#include <string>
#include "WorkItemQueue.h"

using namespace std;

class TTSThreadPool
{
public:
	TTSThreadPool(int nThreads,int qSize);
	virtual ~TTSThreadPool(void);
public:
	/*创建Worker线程池*/
	bool ThreadpoolCreate(int flags);
	/*增加工作任务*/
	int ThreadpoolAdd(IWorkerItem* worker_item);
	/*销毁任务线程*/
	int ThreadpoolDestroy();
	/*释放线程池*/
	int ThreadpoolFree();
	/*获取工作队列实例*/
	WorkItemQueue& GetWorkItemQueue();
	/*获取线程数*/
	int GetThreadCount();
	/*设置任务队列关闭*/
	int ShutDownWorkerQueue();
	/*获取队列关闭状态*/
	int IsWorkerQueueShutDown();
	
public:
	static void* threadpool_thread(void *pThis);
public:
	/*线程池同步锁*/
	pthread_mutex_t lock;
	/*任务队列*/
	pthread_cond_t notify;
	/*任务队列*/
	int started;
	/*任务队列*/
	int shutdown;
private:
	/*任务对列*/
	WorkItemQueue worker_item_queue;
	/*线池中程数*/
	int nThreadCount;
	/*线池中线程句柄*/
	pthread_t *threads;


};

#endif
#include <stdlib.h>
#include "logger.h"
#include "TTSThreadPool.h"

TTSThreadPool::TTSThreadPool(int nThreads,int qSize):nThreadCount(nThreads),shutdown(0),started(0),threads(0)
{
	worker_item_queue.SetWorkerQueueSize(qSize);
	worker_item_queue.SetQueueItemCount(0);
	
}

TTSThreadPool::~TTSThreadPool(void)
{
	if(!ThreadpoolFree())
	{
		LOG_ERROR("Free threadpool failed."); 
	}
	if(!ThreadpoolDestroy())
	{
		LOG_ERROR("Destroy threadpool failed."); 
	}
}

bool TTSThreadPool::ThreadpoolCreate(int flags)
{
    if(nThreadCount <= 0 || nThreadCount > MAX_THREADS_NUM || worker_item_queue.GetWorkerQueueSize() <= 0 || worker_item_queue.GetWorkerQueueSize() > MAX_QUEUE_ITEM_SIZE) 
	{
		LOG_ERROR("Thread Pool Parameter Check error:nThreadCout:%d,nQueueSize:%d",nThreadCount,0); 
		return false;
    }

    this->threads = (pthread_t *)malloc(sizeof(pthread_t) * nThreadCount);

    if((pthread_mutex_init(&(this->lock), NULL) != 0) ||(pthread_cond_init(&(this->notify), NULL) != 0) ||(this->threads == NULL)) 
	{
		LOG_ERROR("pthread_mutex_init && pthread_cond_init init failed,threads mem:%ld",threads);
        int nRet=ThreadpoolFree();
		return false;
    }

    /* 启动 Workerer 线程 */
    for(int i = 0; i < nThreadCount; i++) 
	{
        if(pthread_create(&(this->threads[i]), NULL,threadpool_thread, (void*)this) != 0) 
		{
			LOG_ERROR("The thread %d is create failed...",i);
            ThreadpoolDestroy();
            return false;
        }
        this->started++;
		LOG_INFO("I hv success create %d thread and the thread %d hv started",i,this->started);

    }
    return true;
}

int TTSThreadPool::ThreadpoolAdd(IWorkerItem* worker_item)
{
	int err = THREADPOOL_ERRORNONE;

	if(worker_item == NULL) 
	{
		LOG_ERROR("the workitem is empty......");
		return THREADPOOL_INVALID;
	}

	if(pthread_mutex_lock(&(this->lock)) != 0) 
	{
		LOG_ERROR("Queue lock is init failed...");
		return THREADPOOL_LOCK_FAILURE;
	}

	do {
		LOG_INFO("start to add item into the queue...");
		/* 判断队列是否已满 */
		if(this->GetWorkItemQueue().GetWorkerItemCount() == this->worker_item_queue.GetWorkerQueueSize()) 
		{
			LOG_ERROR("The Queue is full..... pls check...");
			err = THREADPOOL_QUEUE_FULL;
			break;
		}

		/* 判断内存池是否关闭 */
		if(this->shutdown)
		{
			LOG_ERROR("the queue is shutdown.....");
			err = THREADPOOL_SHUTDOWN;
			break;
		}

		/* 增加任务到队列 */
		this->GetWorkItemQueue().PutItem(worker_item);

		/*设置队列信号 */
		if(pthread_cond_signal(&(this->notify)) != 0) 
		{
			LOG_INFO("I hv notify the others......");
			err = THREADPOOL_LOCK_FAILURE;
			break;
		}
	} while(0);

	if(pthread_mutex_unlock(&this->lock) != 0) 
	{
		LOG_ERROR("Unlock the queue......");
		err = THREADPOOL_LOCK_FAILURE;
	}
	return err;
}

int TTSThreadPool::ThreadpoolDestroy()
{
	int i, err = 0;
	if(pthread_mutex_lock(&(this->lock)) != 0)
	{
		return THREADPOOL_LOCK_FAILURE;
	}

	do {
		/* 已经关闭 */
		if(this->shutdown) 
		{
			err = THREADPOOL_SHUTDOWN;
			break;
		}

		this->shutdown = 1 ;

		/* 唤醒所有工作线程 */
		if((pthread_cond_broadcast(&(this->notify)) != 0) ||
			(pthread_mutex_unlock(&(this->lock)) != 0)) 
		{
				err = THREADPOOL_LOCK_FAILURE;
				break;
		}

		/* Join 工作线程 */
		for(i = 0; i < this->nThreadCount; i++) 
		{
			if(pthread_join(this->threads[i], NULL) != 0) {
				err = THREADPOOL_THREAD_FAILURE;
			}
		}
	} while(0);

	/* 释放线程池 */
	if(!err) 
	{
		ThreadpoolFree();
	}
	return err;
}

int TTSThreadPool::ThreadpoolFree()
{
	LOG_ERROR("GetWorkItemQueue is called......");
    if( this->started > 0) 
	{
        return -1;
    }

    /* 释放线程,清空队列 */
    if(this->threads)
	{
        free(this->threads);
		this->threads=NULL;
        this->worker_item_queue.ClearItem();
		/*锁住线程,防止最后冲突*/
        pthread_mutex_lock(&(this->lock));
        pthread_mutex_destroy(&(this->lock));
        pthread_cond_destroy(&(this->notify));
    }
    return 0;
}


WorkItemQueue& TTSThreadPool::GetWorkItemQueue()
{
	return worker_item_queue;
}

int TTSThreadPool::GetThreadCount()
{
	return nThreadCount;
}

int TTSThreadPool::ShutDownWorkerQueue()
{
	this->shutdown=1;
}

int TTSThreadPool::IsWorkerQueueShutDown()
{
	return this->shutdown;
}



void* TTSThreadPool::threadpool_thread(void *pThis)
{
	TTSThreadPool *pPool = (TTSThreadPool*)pThis;
	IWorkerItem* task=NULL;
	for(;;)
	{
		pthread_mutex_lock(&(pPool->lock));

		/* 等待notify 变为受信状态*/
		while((pPool->GetWorkItemQueue().GetWorkerItemCount() == 0) && (!pPool->shutdown)) 
		{
			LOG_INFO("----------------i am waiting-----------------");
			pthread_cond_wait(&(pPool->notify), &(pPool->lock));
		}

		if((pPool->shutdown == 1) ||((pPool->shutdown == 1) &&(pPool->GetWorkItemQueue().GetWorkerItemCount() == 0))) 
		{
			LOG_INFO("------------pool shutdown&&empty--------------");
			break;
		}

		/* 任务出列,准备开始工作 */
		task=(pPool->GetWorkItemQueue()).GetItem();
		
		/* 工作队列减锁 */
		pthread_mutex_unlock(&(pPool->lock));

		/* 任务开始工作*/
		task->WorkerMain((void*)task);

		sleep(0);
	}
	pPool->started--;
	pthread_exit(NULL);
	return NULL;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章