多线程
来源:互联网 发布:linux echo是什么意思 编辑:程序博客网 时间:2024/05/21 06:45
C++中的类与多线程
标签(空格分隔): 学习笔记
背景:项目需求得把原来写的一个单线程版本改为多线程实现,已达到速度需求。原本的单线程版本已经封装好成类。
一、多线程的循环创建、申请、及使用
按照惯例,先贴代码:
//头文件#include <process.h> //创建以及初始化锁HANDLE hMutex;hMutex = CreateMutex(NULL, FALSE, NULL);
//上锁WaitForSingleObject(hMutex, INFINITE);//解锁ReleaseMutex(hMutex);
//循环开辟线程//通过读取计算机的最大可用线程来开辟线程 const int num_threads = 8; HANDLE handle[num_threads]; for (int i = 0; i < num_threads; i++) { //HANDLE handle = INVALID_HANDLE_VALUE; unsigned int id[num_threads] = { 0 }; handle[i] = (HANDLE)_beginthreadex(NULL, 0, singleChannelFunc, this, 0, &id[i]); } WaitForMultipleObjects(num_threads, handle, true, INFINITE); for (int i = 0; i < num_threads; i++) { CloseHandle(handle[i]); }
其中,开辟线程的数目可有自己的程序需求而定,当然如果你需要的线程越多越好,那么下面这个函数可以帮你获取到此台计算机当中最大可用线程,包含头文件”windows.h”
static int get_processor_number(){ SYSTEM_INFO info; GetSystemInfo(&info); return (int)info.dwNumberOfProcessors;}
二、类和多线程之间的调用关系
详细步骤:
1、在开辟线程之前先维护一个队列,该队列存放需要分发给各单个线程的数据信息。(针对我的项目来说,将图像块的起始点位置ij以及图像块的长宽hw存放在队列里面)更为具体的来说,单线程的程序中,分配好图像块之后调用的执行参数压到队列里面。
单线程程序
class A;//分块for(int i = 0;i < rows_num;i++){ for(int j = 0;j < cols_num ;j++) { i_idx = blk.col * i; j_idx = blk.row * j; A.run(i_idx,j_idx,blk.row.blk.col); }}
改写为相应的多线程部分
class Para{ para1; para2; para3; para4;}//维护队列queue <class Para> queue_img_info;//分块for(int i = 0;i < rows_num;i++){ for(int j = 0;j < cols_num ;j++) { i_idx = blk.col * i; j_idx = blk.row * j; Para parameter; parameter.para1 = i_idx; parameter.para2 = j_idx; parameter.para3 = blk.row; parameter.para4 = blk.col; queue_img_info.push(parameter); }}
2、写多线程调用的类内部接口方法和外部单线程工作的接口函数
由于语法的规定,单个线程的执行函数的输入参数必须是void*,则单线程的函数只需要做两件事情:将void*的输入强制类型转换为A*,然后调用A*类的内部多线程接口方法;
外部接口函数,只需要定义每个单个线程需要干什么事就行
unsigned int _stdcall singleChannelFunc(void * pm){ A *ptr_solver = static_cast<A*>(pm); ptr_solver->singleChanFunInterface(); return 0;}
A类内部的多线程接口函数,它需要规定线程锁定释放的顺序
void APSR_solver::singleChanFunInterface(){ while (1) { //有线程进来,立马上锁 WaitForSingleObject(hMutex, INFINITE); //如果队列为空,代表当前没有任务需要进行处理,立马开锁 if (queue_img_info.empty()) { ReleaseMutex(hMutex); break; } //单个线程获得队列信息 Para para = queue_img_info.front(); //将处理的队列中的第一块拿走 queue_img_info.pop(); //开锁 ReleaseMutex(hMutex); //执行单线程任务(A) run(para.para1,para.para2,para.para3,para.para4); }}
3、在类中的执行函数中开辟线程,其中每个线程都调用单线程函数
//开辟线程 const int num_threads = 8; //定义线程句柄 HANDLE handle[num_threads]; for (int i = 0; i < num_threads; i++) { unsigned int id[num_threads] = { 0 }; //将每个线程都关联类外的单线程函数,冰纯如this指针 handle[i] = (HANDLE)_beginthreadex(NULL, 0, singleChannelFunc, this, 0, &id[i]); } //等待多线程执行任务 WaitForMultipleObjects(num_threads, handle, true, INFINITE); //循环关闭句柄 for (int i = 0; i < num_threads; i++) { CloseHandle(handle[i]); }
以上就是将一个封装好的类中的单线程方法改实现为多线程。
0 0