一个简单的线程池

昨天晚上写了一个线程池管理,记录下来吧:


//@author: tigermei
//@data: 2012/03/20
//thread base
#ifndef THREADBASE_H_
#define THREADBASE_H_

//
//macro that is used to prevet copy and assign the object
#define DISALLOW_COPY_AND_ASSIGN(ClassName)      \
	ClassName(const ClassName&);                    \
	void operator=(const ClassName&)

class CThreadBase
{
public:
	CThreadBase();
	virtual ~CThreadBase();

	//
	//start the the thread
	BOOL Start();

	//
	//wait the thread the times of dwElapseTime until the thread is destroyed
	//@dwElapseTime the times that is needed to wait
	BOOL Wait(DWORD dwElapseTime = INFINITE);

	//
	//get the handle of the thread
	HANDLE GetHandle(){ return m_hThreadHandle; }

protected:
	//
	//the function that is needed to be extended
	//it is pure virtual functin, the work thread will call it
	virtual int Run() = 0;

private:
	//
	//the start of the work thread
	static unsigned int __stdcall start_address(void * param);

	DISALLOW_COPY_AND_ASSIGN(CThreadBase);

private:
	//
	//handle of the new work thread
	HANDLE m_hThreadHandle;

	//
	//the id of the new work thread
	DWORD m_dwThreadId;
};

#endif



//@author: tigermei
//@data: 2012/03/20
//thread base

#include "stdafx.h"
#include "ThreadBase.h"
#include <assert.h>
#include <process.h>

CThreadBase::CThreadBase(): m_hThreadHandle(INVALID_HANDLE_VALUE), m_dwThreadId(0)
{

}

CThreadBase::~CThreadBase()
{
	if(m_hThreadHandle != INVALID_HANDLE_VALUE)
		::CloseHandle(m_hThreadHandle);
}

BOOL CThreadBase::Start()
{
	if(m_hThreadHandle != INVALID_HANDLE_VALUE)
	{
		assert(false);
		return FALSE;
	}

	//
	//start a new work thread
	m_hThreadHandle = (HANDLE)_beginthreadex(0, 0,
		start_address, (void *)this, 0, (unsigned int *)&m_dwThreadId);

	return m_hThreadHandle != INVALID_HANDLE_VALUE;
}

unsigned int __stdcall CThreadBase::start_address( void * param)
{
	CThreadBase *pThread = (CThreadBase *)param;
	if(pThread)
	{
		return pThread->Run();
	}
	return 0;
}

BOOL CThreadBase::Wait(DWORD dwElapseTime)
{
	DWORD dwWaitResult = ::WaitForSingleObject(m_hThreadHandle, dwElapseTime);
	if(dwWaitResult == WAIT_OBJECT_0)
		return TRUE;
	else
		return FALSE;
	return FALSE;
}



//@author: tigermei
//@data: 2012/03/20
//Worker thread

#ifndef TASK_H
#define TASK_H_
#include "ThreadBase.h"
#include "Lock.h"
#include <queue>
#include <vector>

#define EVENT_NUM 2

class Request;
class CWorkersMgr;

extern const int NumberOfThreads;

//
//the class CWorker is used to pack the work thread
//
class CWorker : public CThreadBase
{
public:
	//
	//@param pWorkerMgr we need some variables frome the 
	//	object of CWorkersMgr
	CWorker(CWorkersMgr *pWorkerMgr);
	virtual ~CWorker();

	//
	//when we need stop the current thread ,call the function stop
	BOOL Stop();

protected:
	//
	//this function will be called in the worker thread
	virtual int Run();

private:
	//
	//do the real work
	void WorkerThread();

private:
	CWorkersMgr *m_pWorkerMgr;

	//
	//m_hHanleEvent[0] quit event, when we need stop the thread, we signal the event
	//m_hHanleEvent[1] the same as the member of m_hRequestSemaphore in CWorkersMgr
	HANDLE m_hHanleEvent[EVENT_NUM];
};

//
//class CWorkersMgr manage the request queue
//and manage the work threads
//
class CWorkersMgr
{
public:
	CWorkersMgr();
	~CWorkersMgr();

	//
	//Get the request from the queue, we need lock here
	//@return the request in the queue, when we return the request
	//	we also need remove it from the queue
	//
	Request *GetNextRequest();

	//
	//if there is some requestes, we push it into the queue
	//@param pRequest the pointor of the request
	//
	void PushRequest(Request *pRequest);

	//
	//tell if the request queue is empty
	//
	BOOL IsRequestQueueEmpty();

	//
	//create work thread
	//
	void CreateWorkers();

	//wait until the work has been completed
	//
	void WaitUntilWorkComplete();

	//
	//destroy the work thread and some member variables
	//
	void DestroyWorkers();

private:
	void Uninit();

public:
	//m_hRequestSemaphore is used to resume the work thread to process the request
	HANDLE m_hRequestSemaphore;

	//when the request has be completed, m_hRequestComplete will be signaled
	HANDLE m_hRequestComplete;

	//Synchronous different threads to process the task queue
	CLock m_csQueueAccess;

private:
	//Request queue
	std::queue<Request *> m_queueRequest;

	//work thread
	std::vector<CWorker *> m_arrayWorkers;
};
#endif



//@author: tigermei
//@data: 2012/03/20
//Worker thread

#include "stdafx.h"
#include <assert.h>
#include "Work.h"
#include "ThreadBase.h"

extern const int NumberOfThreads;
extern Request * GetRequest() throw();
extern void ProcessRequest(Request * request) throw();

#define TRY_WAIT_TIMES 3

CWorker::CWorker(CWorkersMgr *pWorkerMgr)
{
	m_pWorkerMgr = pWorkerMgr;
	m_hHanleEvent[0] = CreateEvent(NULL, FALSE, FALSE, NULL);

	if(m_pWorkerMgr)
	{
		m_hHanleEvent[1] = m_pWorkerMgr->m_hRequestSemaphore;
	}
}

CWorker::~CWorker()
{
	if(m_hHanleEvent[0])
		::CloseHandle(m_hHanleEvent[0]);
	if(m_hHanleEvent[1])
		m_hHanleEvent[1] = NULL;

}

int CWorker::Run()
{
	WorkerThread();
	return 0;
}

void CWorker::WorkerThread()
{
	//loop here
	for(;;)
	{
		//
		//we wait two events here
		//one is the request event, the other is quit event
		DWORD dwRet = WaitForMultipleObjects(EVENT_NUM, m_hHanleEvent, FALSE, INFINITE);

		if(dwRet == WAIT_OBJECT_0)
		{
			//
			//the quit event has been signaled
			break;
		}
		else if(dwRet == WAIT_OBJECT_0 +1)
		{
			//
			//there are request that needed be processed
			Request *request = m_pWorkerMgr->GetNextRequest();
			ProcessRequest(request);
			delete request;

			//
			//check if there are more request
			//if there is no requestes in the queue,we need signal the complete event
			if(m_pWorkerMgr->IsRequestQueueEmpty())
			{
				::SetEvent(m_pWorkerMgr->m_hRequestComplete);
			}
		}
		else
		{
			assert(false);
			break;
		}
	}

}

BOOL CWorker::Stop()
{
	//
	//signal the quit event so that the worker thread can jump out frome the loop
	::SetEvent(m_hHanleEvent[0]);

	return Wait(20);
}

/CWorkersMgr//
CWorkersMgr::CWorkersMgr()
{
	m_hRequestSemaphore = INVALID_HANDLE_VALUE;
	m_hRequestComplete = INVALID_HANDLE_VALUE;
}

CWorkersMgr::~CWorkersMgr()
{
	m_hRequestSemaphore = INVALID_HANDLE_VALUE;
	m_hRequestComplete = INVALID_HANDLE_VALUE;
}

void CWorkersMgr::CreateWorkers()
{
	m_hRequestSemaphore = ::CreateSemaphore(NULL, 0, 0xff, NULL);
	m_hRequestComplete = ::CreateEvent(NULL, FALSE, TRUE, NULL);
	
	CWorker *pWorkersArray = new CWorker(this);
	for(int i = 0; i < NumberOfThreads ; ++i)
	{
		CWorker *pWorkers = new CWorker(this);
		m_arrayWorkers.push_back(pWorkers);

		//
		//we need start the thread, if there are no request
		//the work thread will wait the request event
		pWorkers->Start();
	}
}

void CWorkersMgr::WaitUntilWorkComplete()
{
	WaitForSingleObject(m_hRequestComplete, INFINITE);
}

void CWorkersMgr::DestroyWorkers()
{
	int nWorkers = m_arrayWorkers.size();
	for(int i = 0 ; i < nWorkers ; ++i)
	{
		//
		//stop the worker thread
		BOOL bStop = m_arrayWorkers[i]->Stop();
		if(!bStop)
		{
			//
			//if not stop, we TRY_WAIT_TIMES times to wait
			//500ms every time
			for(int j = 0;  j < TRY_WAIT_TIMES; ++j)
			{
				bStop = m_arrayWorkers[i]->Wait(500);
				if(bStop) break;
			}

			//
			//After TRY_WAIT_TIMES times try
			//the thread still doesn't stop ,we terminate it
			if(!bStop)
			{
				::TerminateThread(m_arrayWorkers[i]->GetHandle(), 0);
			}
		}
	}

	//
	//uninit other variables
	Uninit();
}

void CWorkersMgr::Uninit()
{
	::CloseHandle(m_hRequestSemaphore);
	::CloseHandle(m_hRequestComplete);

	int nWorkers = m_arrayWorkers.size();
	for(int i = 0 ; i < nWorkers ; ++i)
	{
		CWorker *pWorker = m_arrayWorkers[i];
		delete pWorker;
	}

	while(!m_queueRequest.empty())
	{
		Request *request = m_queueRequest.front();
		m_queueRequest.pop();
		delete request;
	}

}


Request *CWorkersMgr::GetNextRequest()
{
	CAutoLock autoLock(&m_csQueueAccess);
	Request *request = m_queueRequest.front();
	m_queueRequest.pop();
	return request;
}

void CWorkersMgr::PushRequest(Request *pRequest)
{
	if(pRequest)
	{
		//
		//the request queue is shared by main thread and worker threads
		CAutoLock autoLock(&m_csQueueAccess);
		
		m_queueRequest.push(pRequest);

		//
		//when there are requestes, we must set the complete event no signal
		::ResetEvent(m_hRequestComplete);

		//
		//add the request semaphore
		ReleaseSemaphore(m_hRequestSemaphore, 1, NULL);
	}
}

BOOL CWorkersMgr::IsRequestQueueEmpty()
{
	CAutoLock autoLock(&m_csQueueAccess);
	return m_queueRequest.empty();
}



//@author: tigermei
//@data: 2012/03/20
//Lock
#ifndef LOCK_H_
#define LOCK_H_


class CAutoLock;
class CLock
{
public:
CLock();


~CLock();


void Enter();


void Leave();


private:
CRITICAL_SECTION m_CritSect;
};


//
// use example:
//
// CLock lock;
// {
// CAutoLock autoLock(&lock);
// }
//
class CAutoLock
{
public:
CAutoLock(CLock *pLock);
~CAutoLock();


private:
CLock *m_pLock;
};


#endif



//@author: tigermei
//@data: 2012/03/20
//Lock
#include "stdafx.h"
#include "Lock.h"

CLock::CLock()
{
	::InitializeCriticalSection(&m_CritSect);
}

CLock::~CLock()
{
	::DeleteCriticalSection(&m_CritSect);
}

void CLock::Enter()
{
	::EnterCriticalSection(&m_CritSect);
}

void CLock::Leave()
{
	::LeaveCriticalSection(&m_CritSect);
}



CAutoLock::CAutoLock(CLock *pLock)
{
	m_pLock = pLock;

	//
	//Enter the lock
	if(m_pLock)
		m_pLock->Enter();
}

CAutoLock::~CAutoLock()
{
	//
	//Leave the lock
	if(m_pLock)
		m_pLock->Leave();
	m_pLock = NULL;
}


// request.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Work.h"


class Request
{
};

//Returns NULL if you want to complete 
//the process, or a pointer to the memory
Request * GetRequest() throw()
{
	return NULL;
}

//Process the request, but does not remove the memory
void ProcessRequest(Request * request) throw()
{
	return;
}

const int NumberOfThreads = 2;


int _tmain(int argc, _TCHAR* argv[])
{
	CWorkersMgr workersMgr;

	//
	//create work threads
	workersMgr.CreateWorkers();

	// get the request and put it into the queue in workers manager
	Request *request = GetRequest();
	while(request)
	{
		workersMgr.PushRequest(request);
		request = GetRequest();
	}

	//
	//wait until the Request has been processed
	workersMgr.WaitUntilWorkComplete();

	//
	//destroy the work threads
	workersMgr.DestroyWorkers();
	return 0;
}


使用优化算法,以优化VMD算法的惩罚因子惩罚因子 (α) 和分解层数 (K)。 1、将量子粒子群优化(QPSO)算法与变分模态分解(VMD)算法结合 VMD算法背景: VMD算法是一种自适应信号分解算法,主要用于分解信号为不同频率带宽的模态。 VMD的关键参数包括: 惩罚因子 α:控制带宽的限制。 分解层数 K:决定分解出的模态数。 QPSO算法背景: 量子粒子群优化(QPSO)是一种基于粒子群优化(PSO)的一种改进算法,通过量子行为模型增强全局搜索能力。 QPSO通过粒子的量子行为使其在搜索空间中不受位置限制,从而提高算法的收敛速度与全局优化能力。 任务: 使用QPSO优化VMD中的惩罚因子 α 和分解层数 K,以获得信号分解的最佳效果。 计划: 定义适应度函数:适应度函数根据VMD分解的效果来定义,通常使用重构信号的误差(例如均方误差、交叉熵等)来衡量分解的质量。 初始化QPSO粒子:定义粒子的位置和速度,表示 α 和 K 两个参数。初始化时需要在一个合理的范围内为每个粒子分配初始位置。 执行VMD分解:对每一组 α 和 K 参数,运行VMD算法分解信号。 更新QPSO粒子:使用QPSO算法更新粒子的状态,根据适应度函数调整粒子的搜索方向和位置。 迭代求解:重复QPSO的粒子更新步骤,直到满足终止条件(如适应度函数达到设定阈值,或最大迭代次数)。 输出优化结果:最终,QPSO算法会返回一个优化的 α 和 K,从而使VMD分解效果最佳。 2、将极光粒子(PLO)算法与变分模态分解(VMD)算法结合 PLO的优点与适用性 强大的全局搜索能力:PLO通过模拟极光粒子的运动,能够更高效地探索复杂的多峰优化问题,避免陷入局部最优。 鲁棒性强:PLO在面对高维、多模态问题时有较好的适应性,因此适合海上风电时间序列这种非线性、多噪声的数据。 应用场景:PLO适合用于优化VMD参数(α 和 K),并将其用于风电时间序列的预测任务。 进一步优化的建议 a. 实现更细致的PLO更新策略,优化极光粒子的运动模型。 b. 将PLO优化后的VMD应用于真实的海上风电数据,结合LSTM或XGBoost等模型进行风电功率预测。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值