🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## **为什么要采用线程池?** 首先想一想,我们一般的服务器都是动态创建子线程来实现并发服务器的,比如每当有一个客户端请求建立连接时我们就动态调用pthread\_create去创建线程去处理该连接请求。这种模式有什么缺点呢? * 动态创建线程是比较费时的,这将到导致较慢的客户响应。 * 动态创建的子线程通常只用来为一个客户服务,这将导致系统上产生大量的细微线程,线程切换也会耗费CPU时间。 所以我们为了进一步提升服务器性能,可以采取“池”的思路,把线程的创建放在程序的初始化阶段一次完成,这就避免了动态创建线程导致服务器响应请求的性能下降。 ## **线程池的设计思路** 1. 以单例模式设计线程池,保证线程池全剧唯一; 2. 在获取线程池实例进行线程池初始化:线程预先创建+任务队列创建; 3. 创建一个任务类,我们真实的任务会继承该类,完成任务执行1. ``` #include <queue> #include <unistd.h> #include <pthread.h> #include <mutex> #include <vector> #include <stdio.h> typedef struct { int task_id; std::string task_name; }msg_t; class Task { public: Task(void* a = NULL): arg(a) { } void SetArg(void* a) { arg = a; } virtual int run()=0; protected: void* arg; }; class MyTask: public Task { public: int run() { msg_t* msg = (msg_t*)arg; //参数解析 printf("working thread[%lu] : task_id:%d task_name:%s\n", pthread_self(), msg->task_id, msg->task_name.c_str()); sleep(10); return 0; } }; class ThreadPool { private: std::queue<Task*> taskQueue;//任务队列 bool isRunning; //线程池运行标志 pthread_t* pThreadSet; //指向线程id集合的指针 int threadsNum; //线程数目 pthread_mutex_t mutex; //互斥锁 pthread_cond_t condition; //条件变量 ThreadPool(int num = 10):threadsNum(num) { printf ("creating threads %d pool ...\n ", num); isRunning = true; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&condition, NULL); createThreads(); printf("created threads pool successfully!\n"); } void createThreads() { pThreadSet = (pthread_t *) malloc(sizeof(pthread_t) * threadsNum); for(int i = 0; i < threadsNum; ++i) { pthread_create(&pThreadSet[i], NULL, threadFunc, this); } } void clearThreads() { if (!isRunning) return; isRunning = false; pthread_cond_broadcast(&condition); printf("start closing ...\n"); for (int i = 0; i < threadsNum; i ++) { pthread_join(pThreadSet[i], NULL); printf("close thread %lu\n",pThreadSet[i]); } free(pThreadSet); pThreadSet = NULL; pthread_mutex_destroy(&mutex); pthread_cond_destroy(&condition); } void clearQueue() { while(!taskQueue.empty()) { delete(taskQueue.front()); taskQueue.pop(); } } static void* threadFunc(void* arg) { ThreadPool* p = (ThreadPool*)arg; while(p->isRunning) { Task* task = p->takeTask(); if (!task) { continue; } printf("take one ...\n"); task->run(); } } Task* takeTask() { Task* pTask = NULL; while(!pTask) { pthread_mutex_lock(&mutex); while(taskQueue.empty() && isRunning) { pthread_cond_wait(&condition, &mutex); } if (!isRunning) { pthread_mutex_unlock(&mutex); break; } else if (taskQueue.empty()) { pthread_mutex_unlock(&mutex); continue; } pTask = taskQueue.front(); taskQueue.pop(); pthread_mutex_unlock(&mutex); } return pTask; } public : void addTask(Task* pTask) { pthread_mutex_lock(&mutex); taskQueue.push(pTask); printf("one task is put into queue! Current queue size is %lu\n",taskQueue.size()); pthread_mutex_unlock(&mutex); pthread_cond_signal(&condition); } static ThreadPool* createThreadPool(int num = 10) { static ThreadPool* pThreadPoolInstance = new ThreadPool(num); return pThreadPoolInstance; } ~ThreadPool() { clearThreads(); clearQueue(); printf("thread pool is closed!\n"); } int getQueueSize() { pthread_mutex_lock(&mutex); int size = taskQueue.size(); pthread_mutex_unlock(&mutex); printf("current queue size is %d\n", size); return size; } int getThreadNum() { return threadsNum; } }; int main() { ThreadPool* pMyPool = ThreadPool::createThreadPool(5); //建立大小为5的线程池 char buf[32] = {0}; int num = 200; msg_t msg[num]; MyTask task_A[num]; //模拟生产者生产任务 for(int i=0;i<num;i++) { msg[i].task_id = i; sprintf(buf,"qq_task_%d",i); msg[i].task_name = buf; task_A[i].SetArg(&msg[i]); //设置函数参数 pMyPool->addTask(&task_A[i]); //任务入队 sleep(1); } while(1) { //printf("there are still %d tasks need to process\n", pMyPool->getQueueSize()); if (pMyPool->getQueueSize() == 0) { printf("Now I will exit from main\n"); break; } sleep(1); } delete pMyPool; return 0; } ```