尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

基于Linux pthread库模拟实现的线程类

基于Linux pthread库模拟实现的线程类 基于Linux pthread库模拟实现的线程类线程类的本质对线程生命周期的控制线程创建线程属性获取线程等待int(void*) 线程v1.0参考void(T)线程v1.1参考线程类的本质无论什么语言的线程类只要它还在当前计算机中运行就必须调用计算机中原有的原生线程库内的接口对线程进行控制。所以所谓的封装使用的还是原生线程但会根据实际需求例如安全、效率等对创建的线程进行控制。这里模仿 C11 的thread类对线程类进行描述希望一个线程有自己的线程ID。希望线程有自己的线程名。用户可能希望查看当前线程的运行状态。线程拥有属于自己的线程函数。线程可由用户决定何时启动。线程运行结束后不建议可选返回自己的返回值。因为函数有void和其他返回值类型这使得功能实现上变得很复杂。其他可选一般情况下不希望线程自己进行隐式构造一个线程。线程支持移动构造但不能支持拷贝构造。对线程生命周期的控制线程创建这里我们希望线程类的对象能根据用户的需求选择是否创建。所以构造函数只会对线程的基本信息赋值对象真正创建线程还需要调用额外的函数这里可设置接口start。若线程启动成功则设置状态runstate为真。线程属性获取这里的线程类的属性有 3 种线程名。线程运行状态。线程 ID 。分别给不同的属性设置接口即可。线程等待线程和进程一样若线程已经退出则默认返回时会被等待。所以可通过设置等待用的接口join通过pthread_join使得主线程等待子线程。若线程状态变量runstate为假则说明等待成功join返回真。否则join所在的线程会进行等待修改等待结果并返回。int(void*)线程v1.0参考mythread.hpp#pragmaonce#includefunctional#includepthread.h#includestringusingstd::string;// 想让线程的主体函数和main函数一样的运行模式namespacemystd{usingfunc_tstd::functionint(void*);templateclassTclassMyThread{public:MyThread(conststringname,func_t fc,T dataT()):_name(name),_func(fc),_data(data),_tid(pthread_t()),_runstate(false){}~MyThread(){}staticvoid*ThreadRoutine(void*args){// 通过类内方法启动进程// 因为原生线程库无法上传包装器MyThread*tsstatic_castMyThread*(args);ts-_func(args);returnnullptr;}boolstart(){if(pthread_create(_tid,nullptr,ThreadRoutine,this)0){_runstatetrue;returntrue;}returnfalse;}booljoin(){// 线程正常退出if(!_runstate)returntrue;// 主动等待线程// 可以获取返回值现在是模型所以不考虑设为nullptrif(pthread_join(_tid,nullptr)0){_runstatefalse;returntrue;}// 等待失败returnfalse;}// getter接口boolrunstate()const{return_runstate;}stringname()const{return_name;}pthread_ttid()const{return_tid;}private:pthread_t _tid;// 线程IDstring _name;// 线程名bool_runstate;// 线程运行状态func_t _func;// 线程本体函数T _data;// 线程类初始数据};}// namespace mystd测试参考#includemythread.hpp// 为使用mt19937#includechrono#includeiostream#includerandom#includeunistd.h#includevectorusingmystd::MyThread;usingstd::cout;usingstd::endl;usingstd::to_string;usingstd::vector;intf(void*args){sleep(1);MyThreadint*mtdstatic_castMyThreadint*(args);coutmtd-name(), 启动endl;// 精度更高的随机数类std::mt19937_64rng(std::chrono::steady_clock().now().time_since_epoch().count());for(inti1,x0;i5;i){xrng()%100001;coutxendl;sleep(1);}return0;}voidf1(){MyThreadintmyThread(thread1,f);if(myThread.start()){cout主线程thread1运行成功, 运行状态myThread.runstate()endl;}else{cout主线程thread1运行失败\n;}if(myThread.join()){cout主线程等待thread1成功, 运行状态myThread.runstate()endl;}else{cout主线程等待thread1失败\n;}}voidf2(){vectorMyThreadintts;for(inti1;i5;i){string nameThreadto_string(i);ts.push_back(MyThreadint(name,f));}for(autox:ts){if(!x.start()){coutx.name()启动异常\n;exit(-1);}sleep(1);}for(autox:ts){if(!x.join()){coutx.name()回收异常\n;exit(-1);}coutx.name()成功回收\n;}}intmain(){f2();return0;}void(T)线程v1.1参考mythread.hpp#pragmaonce#includefunctional#includepthread.h#includestringnamespacemystd{usingstd::function;usingstd::string;// 因为线程函数的返回值从始至终都没有使用// 所以直接上传返回值为void的函数templateclassTusingfunc_tfunctionvoid(T);// 创造一个支持选择参数类型的线程类模板templateclassTclassMyThread{private:pthread_t _tid;// 线程IDstring _name;// 线程名bool_runstate;// 线程运行状态func_tT_func;// 线程本体函数T _data;// 计划上传给线程本体函数的参数public:explicitMyThread(conststringname,func_tTfc,T data):_tid(pthread_t()),_name(name),_runstate(false),_func(fc),_data(data){}~MyThread(){}staticvoid*ThreadRoutine(void*args){// args一般情况下为线程对象MyThread*tstatic_castMyThread*(args);t-_func(t-_data);returnnullptr;}boolstart(){if(pthread_create(_tid,nullptr,ThreadRoutine,this)0){return_runstatetrue;}returnfalse;}booljoin(){if(!_runstate)returntrue;if(pthread_join(_tid,nullptr)0){_runstatefalse;returntrue;}returnfalse;}// getter接口boolrunstate()const{return_runstate;}stringname()const{return_name;}pthread_ttid()const{return_tid;}};}// namespace mystd测试程序#includemythread.hpp#includeiostream#includestring#includevectorusingnamespacestd;usingnamespacemystd;structThreadData{vectorint_arr;int*_sum;ThreadData(vectorintarr,int*sum):_arr(arr),_sum(sum){}};voidadd(void*args){vectorintarrstatic_castThreadData*(args)-_arr;int*sumstatic_castThreadData*(args)-_sum;for(autox:arr)(*sum)x;}intmain(){vectorinta{1,1,4,5,1,4,0,9,0,9,8,1,0};intsum0;ThreadDatadt(a,sum);string ThreadNamet1;MyThreadThreadData*t1(ThreadName,add,dt);if(t1.start()){if(!t1.join())return-1;}coutsumendl;return0;}但若编译器支持 C11 还是建议使用thread。
返回列表