循环创建多线程时保证参数的有效性

2024-04-11 00:32

本文主要是介绍循环创建多线程时保证参数的有效性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

循环创建多线程时保证参数的有效性    
当我们需要在一个循环中传递参数时,使用使用函数的方法一般都是:    
for(int   I=0;I <100;I++)
{                  
fun(I);           //使用函数传递i   
}    


每一个循环都会等待fun(I);函数执行完后再进行下一个循环。    
但是当我们需要这个循环中创建线程,并将I的参数传递给线程时,如依然使用以上方法,会造成什么情况呢?    
DWORD   WINAPI   ThreadFun(LPVOID   lpParam)
{                             //线程函数                  
Int   *I   =   (int   *)lpParam;                  Return   0;   
}        


int   I;    
for(I=0;I <100;I++)
{    
DWORD   dwThreadId;            HANDLE   hThread;             
hThread   =   CreateThread(NULL,0,ThreadFunc,&I,0,&dwThreadId);  
}    


好了,到这里我们就可以发现,在循环中,我们创建线程并传递的参数是I=1后,主程序有可能在执到下一次循环时,第一次的ThreadFun函数仍未执行,而此时的I已经等2了,如果ThreadFun再来调用               
Int   *I   =   (int   *)lpParam;语句时,显然不是我们想要的结果。        
解决此问题的一种方法,便是可以使用静态数组来保存所要传递的参数。
如下: 
   
int   I;    
static   int   nPara[100];           //此句需定义为全局    
for(I=0;I <100;I++)
{    
DWORD   dwThreadId;    
HANDLE   hThread;    
NPara[I]=I;                 //保存参数          
hThread   =   CreateThread(NULL,0,ThreadFunc,&nPara[I],0,&dwThreadId); 
}    
此时,所有参数均保存在nPara数组中,刚才的问题是解决了。


接下来又有了新的问题,让我们一起来看看吧:  
  1、如果需要创建的线程不止100,而是非常的大,而且我们也并不知道会有多少次循环的时侯。  
  2、如果我们需要传递的参数不单单只是一个int型的I,而是一个类。那么我们声明的时侯


(假设线程数量最大为65535)则:    
static   CMYClass   myClass[65535];   


编译之后,得到的文件将会堆上一大堆的垃圾。相信任何一位程序都不想看到自己的程序上面堆了一堆垃圾在上面吧。 那么,还有没有更好的办法解决呢。答案是一定的,这里,我就讲一下我自己常用的方法:动态创建对像传递参数。
  
一提到动态创建,我们自然会想到new   与   delete   ,
对了,我想说的也正是他们的使用。    
假设参数类型为:    
typedef   struct   _PARA
{  
int   I;            
DWORD   dwNumber;            
HWND   hOther;    
}Para;  


使用new在堆栈中申请一遍空间,在使用完后必需使用delete将其释放。    


int   I;    
for(I=0;I <100;I++)
{    
DWORD   dwThreadId;    
HANDLE   hThread;     
Para   *myPara   =   new   Para;  
MyPara-> I   =   I;   MyPara-> dwNumber   =   0   ;//自定   
MyPara   -> hOther   =   GetSafeHWnd();//当前窗体句柄           
hThread   =   CreateThread(NULL,0,ThreadFunc,myPara,0,&dwThreadId); //线程函数  
}           


DWORD   WINAPI   ThreadFun(LPVOID   lpParam)
{                             
//线程函数                  
Para   *myPara   =   (Para   *)lpParam;                  //执行其他功能
delete   []   myPara;                                 //释放                 
Return   0;   
}  
  
这样的话,也就不怕传递的参数多少与线程的数量太大了。另外如有需要的话可以加上一个线程计数器,保证当前线程的最大数量。   
通常情况,我比较喜欢把线程处理放在一个类中处理,在主程序中尽量不与线程打交道。        


在循环中使用new 可以保证每次申请到的内存的地址不会是同一个(即不会重复),从而传递给每个线程的参数也互不冲突,互不干扰,相互独立,在线程内部使用完参数后,根据接收的地址,使用delete释放申请的内存块。 
用结构,然后将结构的指针传给CreateThread()的参数lpParameter。需要  注意:
结构应该是“静态的”或是“全局的”或者是“动态分配的”。
如果使用局部  变量,有可能在线程调用这个结构时,结构已经不在栈中了。  
struct   StructA  
{           
int   n1,   n2,   n3,   n4,   n5;  
};    


DWORD   WINAPI   ThreadFun(LPVOID*   param)  
{
StructA*   pa   =   (StructA*)param;          //这儿就可以访问结构中的变量了         
//......           return   1;  
}    
void   TestFunc()  
{           
DWORD   dwID;            
//下面的写法不对          
StructA   a;  
        CreateThread(NULL,   0,   ThreadFun,   &a,   0,   &dwID);            
//下面的写法是对的          
static   StructA   a;           
CreateThread(NULL,   0,   ThreadFun,   &a,   0,   &dwID);  

这篇关于循环创建多线程时保证参数的有效性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/892592

相关文章

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

SpringBoot 获取请求参数的常用注解及用法

《SpringBoot获取请求参数的常用注解及用法》SpringBoot通过@RequestParam、@PathVariable等注解支持从HTTP请求中获取参数,涵盖查询、路径、请求体、头、C... 目录SpringBoot 提供了多种注解来方便地从 HTTP 请求中获取参数以下是主要的注解及其用法:1

HTTP 与 SpringBoot 参数提交与接收协议方式

《HTTP与SpringBoot参数提交与接收协议方式》HTTP参数提交方式包括URL查询、表单、JSON/XML、路径变量、头部、Cookie、GraphQL、WebSocket和SSE,依据... 目录HTTP 协议支持多种参数提交方式,主要取决于请求方法(Method)和内容类型(Content-Ty

Spring 依赖注入与循环依赖总结

《Spring依赖注入与循环依赖总结》这篇文章给大家介绍Spring依赖注入与循环依赖总结篇,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. Spring 三级缓存解决循环依赖1. 创建UserService原始对象2. 将原始对象包装成工

Spring创建Bean的八种主要方式详解

《Spring创建Bean的八种主要方式详解》Spring(尤其是SpringBoot)提供了多种方式来让容器创建和管理Bean,@Component、@Configuration+@Bean、@En... 目录引言一、Spring 创建 Bean 的 8 种主要方式1. @Component 及其衍生注解

python中的显式声明类型参数使用方式

《python中的显式声明类型参数使用方式》文章探讨了Python3.10+版本中类型注解的使用,指出FastAPI官方示例强调显式声明参数类型,通过|操作符替代Union/Optional,可提升代... 目录背景python函数显式声明的类型汇总基本类型集合类型Optional and Union(py

Python多线程实现大文件快速下载的代码实现

《Python多线程实现大文件快速下载的代码实现》在互联网时代,文件下载是日常操作之一,尤其是大文件,然而,网络条件不稳定或带宽有限时,下载速度会变得很慢,本文将介绍如何使用Python实现多线程下载... 目录引言一、多线程下载原理二、python实现多线程下载代码说明:三、实战案例四、注意事项五、总结引

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.

Go语言使用Gin处理路由参数和查询参数

《Go语言使用Gin处理路由参数和查询参数》在WebAPI开发中,处理路由参数(PathParameter)和查询参数(QueryParameter)是非常常见的需求,下面我们就来看看Go语言... 目录一、路由参数 vs 查询参数二、Gin 获取路由参数和查询参数三、示例代码四、运行与测试1. 测试编程路

MySQL 数据库表操作完全指南:创建、读取、更新与删除实战

《MySQL数据库表操作完全指南:创建、读取、更新与删除实战》本文系统讲解MySQL表的增删查改(CURD)操作,涵盖创建、更新、查询、删除及插入查询结果,也是贯穿各类项目开发全流程的基础数据交互原... 目录mysql系列前言一、Create(创建)并插入数据1.1 单行数据 + 全列插入1.2 多行数据