Linux C++线程池的实现
来源:互联网 发布:空气污染 知乎 编辑:程序博客网 时间:2024/05/17 11:34
线程池通过pthread_create创建指定数量的线程,线程函数中实现一个循环,循环中调用worker实现不同的功能。每一个任务(worker)中维护有该worker的回调函数、回调函数的参数、任务列表(worker队列)。每一个线程创建后,使用pthread_cond_wait进行阻塞,等待任务列表中有任务进入。
根据业务需要,实现了一个线程池,这个线程池在c++实现时,遇到一个问题:使用c++的普通成员函数不能用作pthread_create函数的线程函数。因为在c语言中线程函数为全局函数,因此,在c++中,pthread_create函数也一定要为static。
因为pthread_create的线程函数为static,因此,在线程中如果需要调用普通成员函数来实现相关的业务逻辑,一个通用的做法是:将类的this指针传给这个静态的线程函数,在这个函数中使用指针调用相关的函数。
示例如下:
注意环境条件与互斥锁的使用
ThreadPool.h头文件:
<pre name="code" class="cpp">#ifndef __THREADPOOL_H__#define __THREADPOOL_H__#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <pthread.h>#include <sys/types.h>#include <assert.h>#include <map>typedef struct worker{ //任务回调函数 void (*process)(void * arg1, void * arg2, void * arg3, void * arg4); void * arg1; void * arg2; void * arg3; void * arg4; struct worker *next;} ThreadWorker;class ThreadPool{public: void ThreadPoolInit(); void ThreadPoolDestroy(); void AddWorker(void (*process)(void * ,void *, void *, void *), void * arg1, void * arg2, void * arg3, void * arg4); int GetWorkerNum(); ThreadPool(int thread_num); ~ThreadPool() {}private: static void * RunHelper(void *); pthread_mutex_t m_queueLock; pthread_cond_t m_queueReady; void * __thread_loop(void * arg); ThreadWorker * m_workerHead; pthread_t * m_threadIdArray; int m_threadNum; int m_workerSize; bool m_shutDown;};#endif
ThreadPool.cpp源文件
<pre name="code" class="cpp">#include "ThreadPool.h"ThreadPool::ThreadPool(int thread_num):m_threadNum(thread_num), m_workerSize(0), m_workerHead(0), m_threadIdArray(0){ m_shutDown = false; pthread_mutex_init(&m_queueLock, NULL); pthread_cond_init(&m_queueReady, NULL); m_threadIdArray = (pthread_t*)malloc(m_threadNum * sizeof(pthread_t));}void ThreadPool::ThreadPoolInit(){ for (int i = 0; i < m_threadNum; ++i) { //RunHelper为静态函数,参数传入this指针 pthread_create(&m_threadIdArray[i], NULL, &RunHelper, (void *)this); } return;}void ThreadPool::ThreadPoolDestroy(){ if(m_shutDown) return; m_shutDown = true; pthread_cond_broadcast(&m_queueReady); for (int i = 0; i < m_threadNum; ++i) { pthread_join(m_threadIdArray[i], NULL); } free(m_threadIdArray); m_threadIdArray = NULL; ThreadWorker * worker = NULL; while(m_workerHead != NULL) { worker = m_workerHead; m_workerHead = m_workerHead->next; free(worker); } pthread_mutex_destroy(&m_queueLock); pthread_cond_destroy(&m_queueReady); delete this;}void ThreadPool::AddWorker(void (*process)(void * ,void *, void *, void *), void * arg1, void * arg2, void * arg3, void * arg4){ ThreadWorker * new_worker = (ThreadWorker *)malloc(sizeof(ThreadWorker)); new_worker->process = process; new_worker->arg1 = arg1; new_worker->arg2 = arg2; new_worker->arg3 = arg3; new_worker->arg4 = arg4; new_worker->next = NULL; pthread_mutex_lock(&m_queueLock); ThreadWorker * wk = m_workerHead; if (wk == NULL) { m_workerHead = new_worker; }else { while(wk->next != NULL) wk = wk->next; wk->next = new_worker; } assert(m_workerHead != NULL); m_workerSize++; pthread_mutex_unlock(&m_queueLock); pthread_cond_signal(&m_queueReady); return;}int ThreadPool::GetWorkerNum(){ return m_workerSize;}void * ThreadPool::__thread_loop(void * arg){#ifdef DEBUG printf("starting thread 0x%x\n", pthread_self());#endif while(1) { pthread_mutex_lock(&m_queueLock); while(m_workerSize == 0 && !m_shutDown) {#ifdef DEBUG printf("thread 0x%x is waiting\n", pthread_self());#endif //当pthread_cond_wait时,m_queueLock解锁,当pthread_cond_wait执行时,m_queueLock加锁 pthread_cond_wait(&m_queueReady, &m_queueLock); } if (m_shutDown) { pthread_mutex_unlock(&m_queueLock);#ifdef DEBUG printf("thread 0x%x will exit\n", pthread_self());#endif pthread_exit(NULL); } assert(m_workerSize != 0); assert(m_workerHead != NULL); m_workerSize--; ThreadWorker * worker = m_workerHead; m_workerHead = m_workerHead->next; pthread_mutex_unlock(&m_queueLock); (*(worker->process))(worker->arg1, worker->arg2, worker->arg3, worker->arg4); free(worker); worker = NULL; } return NULL;}
//静态函数,用于pthread_create调用void * ThreadPool::RunHelper(void * arg){ ((ThreadPool *)arg)->__thread_loop(NULL); return NULL;}
调用main.cpp仅为参考,不能保证运行:
<pre name="code" class="cpp">#include <cut2mesh/PreFix.h>#include <merge_area/MergeArea.h>#include <thread_pool/ThreadPool.h>extern MeshRegions glob_map_mesh_regions;//声明任务回调函数void thread_process_func(void * agr1, void * arg2, void * arg3, void * arg4);int main(int argc, char ** argv){ char * input_path = NULL; char * output_path = NULL; char * input_name = NULL; int thread_num = 1; int c; while((c = getopt(argc, argv, "i::n::o::j::")) != -1) { switch(c) { case 'i': input_path = optarg; break; case 'n': input_name = optarg; break; case 'o': output_path = optarg; break; case 'j': thread_num = atoi(optarg) ? atoi(optarg) : 1; break; case '?': fprintf(stderr, "usage: %s [-i] [-n] [-o] args\n", argv[0]); return -1; break; } } if (input_path == NULL && output_path == NULL && input_name == NULL) { fprintf(stderr, "[-i] [-o] [-n] options can not be empty!\n"); return -1; } Run_Prefix(input_path, output_path, input_name); char mesh_names[255][glob_map_mesh_regions.size()]; Regions regions_array[glob_map_mesh_regions.size()];
//定义一个线程池对象 ThreadPool * pool = new ThreadPool(thread_num);
//初始化线程池,生成线程 pool->ThreadPoolInit(); int i = 0; BOOST_FOREACH(MeshRegionsPair & pair, glob_map_mesh_regions) { strcpy(mesh_names[i], pair.first.c_str()); regions_array[i] = pair.second;
//向内存池中加入任务 pool->AddWorker(thread_process_func, output_path, input_name, mesh_names[i], ®ions_array[i]); ++i; } while(pool->GetWorkerNum() != 0) { double progress = (glob_map_mesh_regions.size() - pool->GetWorkerNum())/glob_map_mesh_regions.size() * 100; printf("\rprocessing: %f%%", progress); sleep(1); } pool->ThreadPoolDestroy(); printf("\rprocessing: 100%%\n"); return 0;}void thread_process_func(void * arg1, void * arg2, void * arg3, void * arg4){ //由于都是void *,将其转为业务函数能调用的参数 char * output_path = (char *)arg1; char * name = (char *)arg2; char * mesh = (char *)arg3; Regions * regions = (Regions *)arg4;#ifdef DEBUG printf("now doing %s\n", mesh);#endif //业务函数 Regions result = RunMergeArea(*regions);#ifdef DEBUG printf("now outputing %s\n", mesh);#endif Write_One_Mesh(output_path, name, mesh, result);}
0 0
- linux线程池的C语言实现
- linux线程池的C语言实现
- linux线程池的C语言实现
- linux线程池的C语言实现
- Linux下C线程池的实现
- linux线程池的C语言实现
- 简单Linux C线程池的实现
- Linux下C线程池的实现
- Linux下C线程池的实现
- Linux下C线程池的实现
- Linux下C线程池的实现
- linux系统c线程池的实现
- linux线程池的C语言实现
- Linux下C线程池的实现
- Linux下C线程池的实现
- Linux C 实现线程池
- linux C线程池实现
- linux c 实现线程池
- 勾股定理
- 面试总结4--多线程问题
- Oracle中的join
- 如何快速突破GRE考试写作【zhasite】
- spring mvc 上传文件
- Linux C++线程池的实现
- 外卖产品(饿了么、美团外卖、百度外卖)竞品分析
- CentOS6.5 安装 OpenFOAM-2.4.0
- mybatis #与$的区别
- 从 NSURLConnection 到 NSURLSession
- Android命名规范
- 几种常用的设计模式介绍
- Get The Sum
- 摩尔斯电码快速记忆