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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章