C++线程池QueueUserWorkItem

xingyun86 2018-7-24 1796

在计算机程序中,线程是一种很重要的资源,使用的恰当可以极大的提高程序的效率,也就是多线程的使用,但是多线程会让应用程序变得异常复杂,会占用大量的系统资源。就像QQ表情一样,每一个QQ表情的闪动都需要构建一个线程,如果用户使用了大量的表情(GIF),将会有多少个线程在运行,系统的性能将大大减少,甚至导致死机。在这种情况下,多线程变得不太合适了,那么什么机制适用于这种情况下呢,这就是线程池。

通常情况下,应用程序中采用异步调用函数的形式来实现多任务,在windows中,系统提供了QueueUserWorkItem函数实现异步调用,这个函数相当于在线程池中建立多个用户工作项目,跟普通线程机制一样,线程池也有线程的同步等机制。查MSDN,可看到QueueUserWorkItem函数语法如下:

BOOL WINAPI QueueUserWorkItem(
  __in      LPTHREAD_START_ROUTINE Function,
  __in_opt  PVOID Context,
  __in      ULONG Flags);

Function就是用户定义的函数,context是P指针,也是Function的参数,Flags表示一组标志值,作用可通过查MSDN看到,这里就不在叙述。

下面实现了一个简单的线程池程序,没有什么大的功能,可以看到线程池的用法。

#include <iostream>
#include <assert.h>
#include <Windows.h>
#include <string>
using namespace std;
DWORD WINAPI TestThreadPool1(PVOID pContext);
DWORD WINAPI TestThreadPool2(PVOID pContext);
DWORD WINAPI TestThreadPool3(PVOID pContext);
 
CRITICAL_SECTION g_cs;
 
int main(int argc, char * argv[])
{
 
	QueueUserWorkItem(TestThreadPool1, L"Hello World", WT_EXECUTEDEFAULT);
	QueueUserWorkItem(TestThreadPool2, L"Hello World", WT_EXECUTEDEFAULT);
	QueueUserWorkItem(TestThreadPool3, L"Hello World", WT_EXECUTEDEFAULT);
	getchar();
	return 0;
}
 
DWORD WINAPI TestThreadPool1(PVOID pContext)
{
 
	for(int i=0;i<=100;i++)
	{
		cout<<"One Thread is : "<<i<<endl;
	}
	
	return 0;
}
DWORD WINAPI TestThreadPool2(PVOID pContext)
{
 
	for(int i=0;i<=100;i++)
	{
		cout<<"Two Thread is : "<<i<<endl;
	}
	return 0;
}
DWORD WINAPI TestThreadPool3(PVOID pContext)
{
 
	for(int i=0;i<=100;i++)
	{
		cout<<"Three Thread is : "<<i<<endl;
	}
	return 0;
}
#include <Windows.h>

#include <stdio.h>

#include <functional>

using namespace std::placeholders;

class Arbitrary {

    public:

        bool UsefulPublicFunction(int uParameter);

    protected:

    private:
        typedef std::function<void (void)> CallbackType;
        static DWORD WINAPI ProcessWorkItem(void* pVoid);
        void PrivateWorkItem1(int arg1, int arg2);
        void PrivateWorkItem2(char * arg1);
};

void Arbitrary::PrivateWorkItem1(int arg1, int arg2)
{
    printf("Numbers are %u %u\n", arg1, arg2);
    return;
}

void Arbitrary::PrivateWorkItem2(char * arg1)
{
    printf("String is %s\n", arg1);
    return;
}

DWORD WINAPI Arbitrary::ProcessWorkItem(void* pVoid)
{
    CallbackType * callback = static_cast<CallbackType *>(pVoid);
    (*callback)();
    delete callback;
    return 0;
}

bool Arbitrary::UsefulPublicFunction(int param1)
{
    QueueUserWorkItem(&ProcessWorkItem, new CallbackType(std::bind(&Arbitrary::PrivateWorkItem1, this, param1, 7)), 0);

    QueueUserWorkItem(&ProcessWorkItem, new CallbackType(std::bind(&Arbitrary::PrivateWorkItem2, this, (char *)"This is my string")), 0);

    Sleep(1000);
    return true;
}

int main(int argc, char ** argv)
{
    Arbitrary x;

    x.UsefulPublicFunction(5);

    return 0;
}
//threadpool:
 
#ifndef __ZGM_THREAD_POOL_H__
#define __ZGM_THREAD_POOL_H__
#pragma once
#include <list>
#include <windows.h>
namespace ZgmPool
{
struct ZgmTask//线程任务基类,所有的线程任务如果需要使用本线程池,则需要申明本类的子类,并重载runFunc方法。
{
ZgmTask(void*p) :param(p),lockCount(0) { }
static int run(void*p)//本线程函数传入QueueUserWorkItem中,包装了runFunc函数,以便统计当前线程运行个数
{
ZgmTask*task = static_cast<ZgmTask*>(p);
 
::InterlockedIncrement(task->lockCount);
int ret = task->runFunc(task->param);
::InterlockedDecrement(task->lockCount);
delete task;//退出时需要删除该任务对象。
return ret;
}
void setCount(long*count) { lockCount = count;}
virtual int runFunc(void*p)=0;
virtual ~ZgmTask() { }
private:
void*param;
long *lockCount;
};
class ZgmThreadPool
{
class ZgmLock//锁对象,用于互斥变量方便的锁定/解锁。
{
HANDLE handle;
ZgmLock(const ZgmLock&);
ZgmLock& operator=(const ZgmLock&);
public:
explicit ZgmLock(HANDLE hMutex) : handle(hMutex){ ::WaitForSingleObject(handle,INFINITE); }
~ZgmLock(){ ::ReleaseMutex(handle); }
};
HANDLE pthread;
HANDLE hMutex;
long lockCount;
long maxThreads;
bool bExit;
std::list<ZgmTask*> tasks;
public:
ZgmThreadPool(long mThreads) : maxThreads(mThreads),lockCount(0)
{
bExit = false;
hMutex = ::CreateMutex(0,false,0);
pthread = ::CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ZgmThreadPool::run, this, 0, 0);
}
void AddTask(ZgmTask*task)
{
ZgmLock l(hMutex);//获得线程锁
task->setCount(&lockCount);//添加任务之前需要将统计的线程个数传入具体task类中,以便该task本身计算自己线程是否退出。
tasks.push_back(task);
}
~ZgmThreadPool()
{
bExit = true;
CloseHandle(hMutex);
CloseHandle(pthread);
}
// 线程控制函数,用于线程池控制,主要目的是为了不间断的查看task列表中是否有任务,
// 有并且还不到线程最大值,则开启一个线程任务,否则挂起。
static int run(void*p)
{
ZgmThreadPool*pool = static_cast<ZgmThreadPool*>(p);
while( !pool->bExit )
{
if( ( pool->lockCount < pool->maxThreads ) && pool->tasks.size())
{
ZgmLock l(pool->hMutex);//获得线程锁
::QueueUserWorkItem((LPTHREAD_START_ROUTINE)ZgmTask::run,pool->tasks.back(),1);//开启线程任务
pool->tasks.pop_back();
}
//挂起
Sleep(0);
}
return 0;
}
};
}
#endif // __ZGM_THREAD_POOL_H__


×
打赏作者
最新回复 (0)
只看楼主
全部楼主
返回