多线程学习笔记
2016-04-23 19:39
169 查看
头文件windows.h
创建线程
该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄。
lpThreadAttributes:指向一个 SECURITY_ATTRIBUTES 结构的指针,该结构决定了线程的安全属性,一般置为 NULL;
dwStackSize:指定了线程的堆栈深度,一般都设置为0;
lpStartAddress:表示新线程开始执行时代码所在函数的地址,即线程的起始地址。一般情况为线程函数名;
lpParameter:指定了线程执行时传送给线程的32位参数,即线程函数的参数;
dwCreationFlags:控制线程创建的附加标志,可以取两种值。如果该参数为0,线程在被创建后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,该线程处于挂起状态,并不马上执行,直至函数ResumeThread被调用;
lpThreadId:该参数返回所创建线程的ID; 如果创建成功则返回线程的句柄,否则返回NULL
该函数用于挂起指定的线程,如果函数执行成功,则线程的执行被终止 .
该函数用于结束线程的挂起状态,执行线程。
该函数用于线程终结自身的执行
强行终止某一线程的执行
自己写的一个简易的线程类:
该类可以调用带参数的线程函数或者不带参数的线程函数,线程函数返回值类型为int,将放在ret中
使用:
线程函数定义:
一个线程池的实现:
ThreadPool Code
使用:
创建线程
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId )
该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄。
lpThreadAttributes:指向一个 SECURITY_ATTRIBUTES 结构的指针,该结构决定了线程的安全属性,一般置为 NULL;
dwStackSize:指定了线程的堆栈深度,一般都设置为0;
lpStartAddress:表示新线程开始执行时代码所在函数的地址,即线程的起始地址。一般情况为线程函数名;
lpParameter:指定了线程执行时传送给线程的32位参数,即线程函数的参数;
dwCreationFlags:控制线程创建的附加标志,可以取两种值。如果该参数为0,线程在被创建后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,该线程处于挂起状态,并不马上执行,直至函数ResumeThread被调用;
lpThreadId:该参数返回所创建线程的ID; 如果创建成功则返回线程的句柄,否则返回NULL
SuspendThread(HANDLE hThread);
该函数用于挂起指定的线程,如果函数执行成功,则线程的执行被终止 .
DWORD ResumeThread(HANDLE hThread);
该函数用于结束线程的挂起状态,执行线程。
VOID ExitThread(DWORD dwExitCode);
该函数用于线程终结自身的执行
BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode);
强行终止某一线程的执行
自己写的一个简易的线程类:
#include <stdio.h> #include <windows.h> class unit { public: void *v; //参数 int *ret; //返回值 }; class THREAD { public: HANDLE hThread; //线程句柄 DWORD ThreadID; //线程id LPTHREAD_START_ROUTINE IpStartAddress; //线程函数 int ret; //返回值 unit u; //将参数和返回值打包传入线程函数 THREAD() { //初始化 ret = 0; } THREAD(void *ThreadProcess) { //带参数初始化 ret = 0; IpStartAddress = (LPTHREAD_START_ROUTINE)ThreadProcess; } void run() { //运行线程 if (IpStartAddress != NULL) { u = { NULL,&ret }; hThread = CreateThread(NULL, 0, IpStartAddress, (LPVOID)&u, 0, &ThreadID); } } void run(void *lp) { //运行线程,并传入参数 if (IpStartAddress != NULL) { u = { lp,&ret }; hThread = CreateThread(NULL, 0, IpStartAddress, (LPVOID)&u, 0, &ThreadID); } } };
该类可以调用带参数的线程函数或者不带参数的线程函数,线程函数返回值类型为int,将放在ret中
使用:
THREAD fightthread; //创建线程类 fightthread.IpStartAddress = (LPTHREAD_START_ROUTINE)waitFight;//线程函数赋值 fightthread.run(); //运行线程
线程函数定义:
void waitFight(LPVOID pM) { unit* c=(unit*)pM; //参数类型为上边定义的unit类,类里的参数v可以是任意类型的参数 函数体; ...... unit->ret=0; //线程函数返回值赋值 }
一个线程池的实现:
#pragma warning(disable: 4530) #pragma warning(disable: 4786) #include <stdio.h> #include <cassert> #include <vector> #include <queue> #include <windows.h> using namespace std; class ThreadJob //工作基类 { public: //供线程池调用的虚函数 virtual void DoJob(void *pPara) = 0; }; class ThreadPool { public: //dwNum 线程池规模 ThreadPool(DWORD dwNum = 4) : _lThreadNum(0), _lRunningNum(0) { InitializeCriticalSection(&_csThreadVector); InitializeCriticalSection(&_csWorkQueue); _EventComplete = CreateEvent(0, false, false, NULL); _EventEnd = CreateEvent(0, true, false, NULL); _SemaphoreCall = CreateSemaphore(0, 0, 0x7FFFFFFF, NULL); _SemaphoreDel = CreateSemaphore(0, 0, 0x7FFFFFFF, NULL); assert(_SemaphoreCall != INVALID_HANDLE_VALUE); assert(_EventComplete != INVALID_HANDLE_VALUE); assert(_EventEnd != INVALID_HANDLE_VALUE); assert(_SemaphoreDel != INVALID_HANDLE_VALUE); AdjustSize(dwNum <= 0 ? 4 : dwNum); } ~ThreadPool() { DeleteCriticalSection(&_csWorkQueue); CloseHandle(_EventEnd); CloseHandle(_EventComplete); CloseHandle(_SemaphoreCall); CloseHandle(_SemaphoreDel); vector<ThreadItem*>::iterator iter; for (iter = _ThreadVector.begin(); iter != _ThreadVector.end(); iter++) { if (*iter) delete *iter; } DeleteCriticalSection(&_csThreadVector); } //调整线程池规模 int AdjustSize(int iNum) { if (iNum > 0) { ThreadItem *pNew; EnterCriticalSection(&_csThreadVector); for (int _i = 0; _i<iNum; _i++) { _ThreadVector.push_back(pNew = new ThreadItem(this)); assert(pNew); pNew->_Handle = CreateThread(NULL, 0, DefaultJobProc, pNew, 0, NULL); // set priority SetThreadPriority(pNew->_Handle, THREAD_PRIORITY_BELOW_NORMAL); assert(pNew->_Handle); } LeaveCriticalSection(&_csThreadVector); } else { iNum *= -1; ReleaseSemaphore(_SemaphoreDel, iNum > _lThreadNum ? _lThreadNum : iNum, NULL); } return (int)_lThreadNum; } //调用线程池 void Call(void(*pFunc)(void *), void *pPara = NULL) { assert(pFunc); EnterCriticalSection(&_csWorkQueue); _JobQueue.push(new JobItem(pFunc, pPara)); LeaveCriticalSection(&_csWorkQueue); ReleaseSemaphore(_SemaphoreCall, 1, NULL); } //调用线程池 inline void Call(ThreadJob * p, void *pPara = NULL) { Call(CallProc, new CallProcPara(p, pPara)); } //结束线程池, 并同步等待 bool EndAndWait(DWORD dwWaitTime = INFINITE) { SetEvent(_EventEnd); return WaitForSingleObject(_EventComplete, dwWaitTime) == WAIT_OBJECT_0; } //结束线程池 inline void End() { SetEvent(_EventEnd); } inline DWORD Size() { return (DWORD)_lThreadNum; } inline DWORD GetRunningSize() { return (DWORD)_lRunningNum; } bool IsRunning() { return _lRunningNum > 0; } protected: //工作线程 static DWORD WINAPI DefaultJobProc(LPVOID lpParameter = NULL) { ThreadItem *pThread = static_cast<ThreadItem*>(lpParameter); assert(pThread); ThreadPool *pThreadPoolObj = pThread->_pThis; assert(pThreadPoolObj); InterlockedIncrement(&pThreadPoolObj->_lThreadNum); HANDLE hWaitHandle[3]; hWaitHandle[0] = pThreadPoolObj->_SemaphoreCall; hWaitHandle[1] = pThreadPoolObj->_SemaphoreDel; hWaitHandle[2] = pThreadPoolObj->_EventEnd; JobItem *pJob; bool fHasJob; for (;;) { DWORD wr = WaitForMultipleObjects(3, hWaitHandle, false, INFINITE); //响应删除线程信号 if (wr == WAIT_OBJECT_0 + 1) break; //从队列里取得用户作业 EnterCriticalSection(&pThreadPoolObj->_csWorkQueue); if (fHasJob = !pThreadPoolObj->_JobQueue.empty()) { pJob = pThreadPoolObj->_JobQueue.front(); pThreadPoolObj->_JobQueue.pop(); assert(pJob); } LeaveCriticalSection(&pThreadPoolObj->_csWorkQueue); //受到结束线程信号 确定是否结束线程(结束线程信号 && 是否还有工作) if (wr == WAIT_OBJECT_0 + 2 && !fHasJob) break; if (fHasJob && pJob) { InterlockedIncrement(&pThreadPoolObj->_lRunningNum); pThread->_dwLastBeginTime = GetTickCount(); pThread->_dwCount++; pThread->_fIsRunning = true; pJob->_pFunc(pJob->_pPara); //运行用户作业 delete pJob; pThread->_fIsRunning = false; InterlockedDecrement(&pThreadPoolObj->_lRunningNum); } } //删除自身结构 EnterCriticalSection(&pThreadPoolObj->_csThreadVector); pThreadPoolObj->_ThreadVector.erase(find(pThreadPoolObj->_ThreadVector.begin(), pThreadPoolObj->_ThreadVector.end(), pThread)); LeaveCriticalSection(&pThreadPoolObj->_csThreadVector); delete pThread; InterlockedDecrement(&pThreadPoolObj->_lThreadNum); if (!pThreadPoolObj->_lThreadNum) //所有线程结束 SetEvent(pThreadPoolObj->_EventComplete); return 0; } //调用用户对象虚函数 static void CallProc(void *pPara) { CallProcPara *cp = static_cast<CallProcPara *>(pPara); assert(cp); if (cp) { cp->_pObj->DoJob(cp->_pPara); delete cp; } } //用户对象结构 struct CallProcPara { ThreadJob* _pObj;//用户对象 void *_pPara;//用户参数 CallProcPara(ThreadJob* p, void *pPara) : _pObj(p), _pPara(pPara) { }; }; //用户函数结构 struct JobItem { void(*_pFunc)(void *);//函数 void *_pPara; //参数 JobItem(void(*pFunc)(void *) = NULL, void *pPara = NULL) : _pFunc(pFunc), _pPara(pPara) { }; }; //线程池中的线程结构 struct ThreadItem { HANDLE _Handle; //线程句柄 ThreadPool *_pThis; //线程池的指针 DWORD _dwLastBeginTime; //最后一次运行开始时间 DWORD _dwCount; //运行次数 bool _fIsRunning; ThreadItem(ThreadPool *pthis) : _pThis(pthis), _Handle(NULL), _dwLastBeginTime(0), _dwCount(0), _fIsRunning(false) { }; ~ThreadItem() { if (_Handle) { CloseHandle(_Handle); _Handle = NULL; } } }; std::queue<JobItem *> _JobQueue; //工作队列 std::vector<ThreadItem *> _ThreadVector; //线程数据 CRITICAL_SECTION _csThreadVector, _csWorkQueue; //工作队列临界, 线程数据临界 HANDLE _EventEnd, _EventComplete, _SemaphoreCall, _SemaphoreDel;//结束通知, 完成事件, 工作信号, 删除线程信号 long _lThreadNum, _lRunningNum; //线程数, 运行的线程数 };
ThreadPool Code
使用:
ThreadPool tp(10); tp.Call(函数名[,函数参数]);
相关文章推荐
- 编程之美斐波那契数列
- Linux内核模块的概念和基本的编程方法
- Node.js开发入门(六)——使用jade模板引擎
- Android学习分享-常见控件01-TextView详解
- MySQL 高可用:mysql-mmm 负载均衡及故障转移
- 写了一个方便抓Android系统日志的BAT脚本
- 用C语言实现简单的计算器(加、减、乘、除)
- 如何让Anddroid手机访问电脑的Tomcat服务
- hdu 3242 List Operations
- Linux内核
- Node.js开发入门(五)——Express里的路由和中间件
- mybatis如何防止sql注入
- 防止 jsp被sql注入的五种方法
- Window Server IIS6.0部署webservice请求调用提示请求失败
- Javaweb开发之路
- 快速矩阵幂乘算法
- iOS 开发流程笔记
- ASIHTTPRequest
- B - 素数判定 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
- Cracking Story - How I Cracked Over 122 Million SHA1 and MD5 Hashed Passwords