您的位置:首页 > 其它

池化技术 漫谈

2015-01-13 22:12 351 查看
池化技术 - 简单点来说,就是提前保存大量的资源,以备不时之需,O(∩_∩)O,对于线程,内存,oracle的连接对象等等,这些都是资源,程序中当你创建一个线程或者在堆上申请一块内存时,都涉及到很多系统调用,也是非常消耗CPU的,如果你的程序需要很多类似的工作线程或者需要频繁的申请释放小块内存,如果没有在这方面进行优化,那很有可能这部分代码将会成为影响你整个程序性能的瓶颈。池化技术主要有线程池,内存池,连接池,对象池等等,对象池就是提前创建很多对象,将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用,连接池比较典型的有oracle的连接池,了解不深。

下面主要谈谈线程池和内存池,因为这两种技术的通用性和实用性也是比较强的,描述语言C++,其实线程池的话用什么实现都可以。

先来谈谈线程池技术,线程池的框架早就有先辈给我们想好了,也就不用我们去冥思苦想了,我们要做的就是把先辈的想法发现即可。

其实线程池的原理很简单,类似于操作系统中的缓冲区的概念,它的流程如下:先启动若干数量的线程,并让这些线程都处于睡眠状态,当客户端有一个新请求时,就会唤醒线程池中的某一个睡眠线程,让它来处理客户端的这个请求,当处理完这个请求后,线程又处于睡眠状态。可能你也许会问:为什么要搞得这么麻烦,如果每当客户端有新的请求时,我就创建一个新的线程不就完了?这也许是个不错的方法,因为它能使得你编写代码相对容易一些,但你却忽略了一个重要的问题?性能!尤其是对于服务器程序尤为重要,服务器程序会先初始化很多线程在那里等待,当有客户连接时,就激活其中的一个线程来处理客户请求,对于不支持动态增加的线程池,如果没有等待线程,客户就必学等待,而对于能动态增加线程的线程池,则可以像线程池中新加一个线程。

下面是一个用c++实现的线程池,支持动态增减线程数量:

/* -------------------------------------------------------------------------
// 文件名 : KThreadPool.h
// 创建者 : magicTong
// 创建时间 : 2008-10-23 15:02:31
// 功能描述 : 线程池声明
//
// $Id: $
// -----------------------------------------------------------------------*/
#ifndef __KTHREADPOOL_H__
#define __KTHREADPOOL_H__

// -------------------------------------------------------------------------

#include <windows.h>
#include <list>

using namespace std;

// 线程函数指针定义
typedef DWORD (WINAPI *PTHREAD_FUNC_EX)(LPVOID lpThreadParameter);

// 线程状态枚举
typedef enum _enumKThreadStatus
{
THREADRUN, // 运行
THREADPAUSE, // 暂停
}
KThreadStatus;

// -------------------------------------------------------------------------
// 类名 : KThread
// 功能 : 线程类,可动态更换执行函数
// 附注 :
// -------------------------------------------------------------------------
class KThread
{
public:
// 构造
KThread();

// 析构
~KThread();

// -------------------------------------------------------------------------
// 函数 : Init
// 功能 : 初始化函数
// 返回值 : bool
// 附注 :
// -------------------------------------------------------------------------
bool Init();

// -------------------------------------------------------------------------
// 函数 : Run
// 功能 : 运行线程
// 返回值 : bool
// 附注 :
// -------------------------------------------------------------------------
bool Run();

// -------------------------------------------------------------------------
// 函数 : Pause
// 功能 : 暂停线程
// 返回值 : bool
// 附注 :
// -------------------------------------------------------------------------
bool Pause();

// -------------------------------------------------------------------------
// 函数 : Join
// 功能 : 调用Join的线程将阻塞,直到该线程执行完毕
// 返回值 : void
// 附注 :
// -------------------------------------------------------------------------
void Join();

// -------------------------------------------------------------------------
// 函数 : SetProc
// 功能 : 设置线程运行的函数,和要传给线程的参数
// 返回值 : void
// 参数 : PTHREAD_FUNC_EX proc
// 参数 : void* lpParam
// 附注 :
// -------------------------------------------------------------------------
void SetProc(PTHREAD_FUNC_EX proc, void* lpParam);

protected:
KThread(KThread&){}

// 线程实际运行的函数
static DWORD WINAPI RealThreadProc(void* lpParam);

friend class KThreadPool;

protected:
struct KThreadParam
{
PTHREAD_FUNC_EX proc; // 用户线程函数
void *lpParam; // 用户线程参数
KThread *pThread; // 线程类对象
};

HANDLE m_hThread;
DWORD m_id;
KThreadParam m_param;
KThreadStatus m_status;

HANDLE m_hEvt;
HANDLE m_hMtx;
};

// -------------------------------------------------------------------------
// 类名 : KThreadPool
// 功能 : 线程池类声明
// 附注 :
// -------------------------------------------------------------------------
class KThreadPool
{
public:

//构造,initNum初始情况线程数量
KThreadPool(int initNum);

//析构
~KThreadPool();

// -------------------------------------------------------------------------
// 函数 : DoWork
// 功能 : 申请线程进行工作,proc工作函数,lpParam工作函数参数,run是否立即运行,返回线程ID
// 返回值 : DWORD
// 参数 : PTHREAD_FUNC_EX proc
// 参数 : void *lpParam
// 参数 : bool run = true
// 附注 :
// -------------------------------------------------------------------------
DWORD DoWork(PTHREAD_FUNC_EX proc, void *lpParam, bool run = true);

// -------------------------------------------------------------------------
// 函数 : Run
// 功能 : 运行线程,id线程ID
// 返回值 : bool
// 参数 : DWORD id
// 附注 :
// -------------------------------------------------------------------------
bool Run(DWORD id);

// -------------------------------------------------------------------------
// 函数 : Pause
// 功能 : 暂停运行线程,id线程ID
// 返回值 : bool
// 参数 : DWORD id
// 附注 :
// -------------------------------------------------------------------------
bool Pause(DWORD id);

//调整线程池大小为size,返回调整后线程池大小
unsigned SetSize(unsigned size);

protected:
list<KThread*> m_lst;
};

实现:

/* -------------------------------------------------------------------------
// 文件名 : KThreadPool.cpp
// 创建者 : magicTong
// 创建时间 : 2008-10-23 15:02:22
// 功能描述 : 线程池定义
//
// $Id: $
// -----------------------------------------------------------------------*/

#include "stdafx.h"
#include "KThreadPool.h"

// -------------------------------------------------------------------------

// -------------------------------------------------------------------------
// KThread类定义开始
// -------------------------------------------------------------------------
KThread::KThread(): m_hThread(NULL),
m_status(THREADPAUSE),
m_hEvt(0),
m_hMtx(0)
{
}

KThread::~KThread()
{
::CloseHandle(m_hMtx);
if (::TerminateThread(m_hThread, -1) == 0)
return;
}

bool KThread::Init()
{
m_hThread = ::CreateThread(
0,
0,
(PTHREAD_FUNC_EX)(KThread::RealThreadProc),
(void*)&m_param,
CREATE_SUSPENDED,
&m_id);

// 创建线程失败
if (NULL == m_hThread)
{
return false;
}
m_param.proc = NULL;
m_param.lpParam = NULL;
m_param.pThread = this;

//自动复位
m_hEvt = ::CreateEvent(0, FALSE, FALSE, 0);
if (m_hEvt == 0)
{
::CloseHandle(m_hThread);
return false;
}

m_hMtx = ::CreateMutex(0, 0, 0);
if (m_hMtx == 0)
{
::CloseHandle(m_hEvt);
::CloseHandle(m_hThread);
return false;
}

return true;
}

bool KThread::Run()
{
::WaitForSingleObject(m_hMtx, INFINITE);
if (m_status == THREADPAUSE)
if (::ResumeThread(m_hThread) == -1)
{
::ReleaseMutex(m_hMtx);
return false;
}

m_status = THREADRUN;
::ReleaseMutex(m_hMtx);
return true;
}

bool KThread::Pause()
{
::WaitForSingleObject(m_hMtx, INFINITE);
if (m_status == THREADRUN)
if (::SuspendThread(m_hThread) == -1)
{
::ReleaseMutex(m_hMtx);
return false;
}

m_status = THREADPAUSE;
::ReleaseMutex(m_hMtx);
return true;
}

void KThread::Join()
{
::WaitForSingleObject(m_hEvt, INFINITE);
}

void KThread::SetProc(PTHREAD_FUNC_EX proc, void* lpParam)
{
::WaitForSingleObject(m_hMtx, INFINITE);
m_param.proc = proc;
m_param.lpParam = lpParam;
::ReleaseMutex(m_hMtx);
}

DWORD WINAPI KThread::RealThreadProc(void* lpParam)
{
PTHREAD_FUNC_EX proc;
KThreadParam *pp = (KThreadParam*)lpParam;
while (true)
{
proc = pp->proc;
if (proc)
(*proc)(pp->lpParam);
pp->proc = NULL;
pp->lpParam = NULL;
pp->pThread->Pause();
::SetEvent(pp->pThread->m_hEvt);
}
}
// -------------------------------------------------------------------------
// KThread类定义结束
// -------------------------------------------------------------------------

// -------------------------------------------------------------------------
// KThreadPool类定义开始
// -------------------------------------------------------------------------
KThreadPool::KThreadPool(int initNum)
{
KThread *pt;
for (int i = 0; i < initNum; i++)
{
pt = new KThread;
if (pt->Init())
m_lst.push_back(pt);
}
}

KThreadPool::~KThreadPool()
{
list<KThread*>::iterator itBegin = m_lst.begin();
list<KThread*>::iterator itEnd = m_lst.end();
for ( ; itBegin != itEnd; itBegin++)
{
delete (*itBegin);
}
}

DWORD KThreadPool::DoWork(LPTHREAD_START_ROUTINE proc, void *lpParam, bool run)
{
list<KThread*>::iterator itBegin = m_lst.begin();
list<KThread*>::iterator itEnd = m_lst.end();
for (; itBegin != itEnd; itBegin++)
{
if ((*itBegin)->m_param.proc == NULL && (*itBegin)->m_status == THREADPAUSE)
{
(*itBegin)->SetProc(proc, lpParam);

// 立即运行
if (run)
(*itBegin)->Run();
return (*itBegin)->m_id;
}
}

// 没有空闲线程,新建一个新的线程,加入链表
KThread *pt = new KThread;
if (pt->Init())
m_lst.push_back(pt);
pt->SetProc(proc, lpParam);
if (run)
pt->Run();
return pt->m_id;
}

bool KThreadPool::Run(DWORD id)
{
list<KThread*>::iterator itBegin = m_lst.begin();
list<KThread*>::iterator itEnd = m_lst.end();
for (; itBegin != itEnd; itBegin++)
{
if ((*itBegin)->m_id == id)
return ((*itBegin)->Run());
}

return false;
}

bool KThreadPool::Pause(DWORD id)
{
list<KThread*>::iterator itBegin = m_lst.begin();
list<KThread*>::iterator itEnd = m_lst.end();
for (; itBegin != itEnd; itBegin++)
{
if ((*itBegin)->m_id == id)
return ((*itBegin)->Pause());
}

return false;
}

// -------------------------------------------------------------------------
// 函数 : KThreadPool::SetSize
// 功能 : 修改线程池的大小
// 返回值 : unsigned
// 参数 : unsigned size
// 附注 : 如果小缩小线程池大小,谨慎使用
// -------------------------------------------------------------------------
unsigned KThreadPool::SetSize(unsigned size)
{
unsigned nowsize = m_lst.size();
if (nowsize <= size)
{
KThread *pt;
unsigned inc = size - nowsize;
for (unsigned i = 0; i < inc; i++)
{
pt = new KThread;
if (pt->Init())
{
m_lst.push_back(pt);
}
}
return size;
}
else
{
unsigned dec = nowsize - size;
list<KThread*>::iterator it = m_lst.begin();
list<KThread*>::iterator ite = m_lst.end();
list<KThread*>::iterator itemp;
unsigned i = 0;
for (; it != ite && i < dec;)
{
if ((*it)->m_status == THREADPAUSE)
{
itemp = it++;
delete ((*itemp));
m_lst.erase(itemp);
i++;
continue;
}
it++;
}

::Sleep(100 * i);
return m_lst.size();
}
}
// -------------------------------------------------------------------------
// KThreadPool类定义结束
// -------------------------------------------------------------------------

使用:

要定义一个线程函数,然后再将该函数和线程数量设置到内存池中,测试代码如下:

DWORD WINAPI threadFunc(LPVOID lpThreadParam);
void CKThreadPoolExDlg::OnBtnCreate()
{
static i = 0;
if (!m_pThreadPool)
{
m_pThreadPool = new KThreadPool(1);
}

m_pThreadPool->DoWork(threadFunc, this, true);
i++;
if (i == 4)
{
m_pThreadPool->SetSize(10);
}
}

void CKThreadPoolExDlg::DoSomething()
{
//MessageBox("O(∩_∩)O哈哈~");
while (true)
{
::EnterCriticalSection(&m_cs);
DWORD id = GetCurrentThreadId();
CString cstr;
cstr.Format("线程 %d 正在运行...", id);
m_listInfo.InsertItem(m_listInfo.GetItemCount(), cstr);
::LeaveCriticalSection(&m_cs);
::Sleep(400);
}
}

DWORD WINAPI threadFunc(LPVOID lpThreadParam)
{
CKThreadPoolExDlg *pdlg = (CKThreadPoolExDlg *)lpThreadParam;
pdlg->DoSomething();
return 0;
}

代码的详细注释我就不写了,想弄懂原理的还是好好研究下再使用,我不保证里面没有BUG。

再来看看内存池的原理,我下面的参考资料里面有几篇文章讲得不错,想了解原理的可以去看看。

如何更好的管理在应用程序中内存的使用,同时提高内存使用的效率,这是值得每一个开发人员深思的问题。内存池(Memory pool)提供了一种比较可行的解决方案。首先是创建内存池。这个过程的主要任务是预先分配足够大的内存,形成一个初步的“内存池”。分配内存,也就是用户请求内存时,会返回内存池中一块空闲的内存,并将其标志置为已使用,当然具体细节和方法有很多。释放内存时,不是真正地调用free或是delete的过程,而是把内存放回内存池的过程。在把内存放入内存池的同时,要把标志位置为空闲。最后在应用程序结束时,要把内存池销毁。这里主要做的工作就是把内存池中的每一块内存释放。

使用内存池的好处:

1、减少了内存碎片的产生。这个可以从创建内存池的过程中看出。我们在创建内存池时,分配的都是一块块比较整的内存块,这样可以减少内存碎片的产生。

2、提高了内存的使用效率。这个可以从分配内存和释放内存的过程中看出。每次的分配与释放并不是去调用系统提供的函数或是操作符去操作实际的内存,而是在复用内存池中的内存。

缺点就是很有可能会造成内存的浪费,原因也很明显,开始分配了一大块内存,不是全部都用得到的。

针对内存池,这里有两个实现,头一个很简单,用到了STL的队列来管理内存池指针,而且如果分配的内存没有显示的归还给内存池的话,即使内存池销毁的时候,这块内存也不会被销毁,就会有内存泄露,当然这个程序还可以改进,另外一个程序是根据《C++应用程序性能优化》中提到的一种方法来实现的,程序见下面:

简单实现(还有很大的改进余地):

/* -------------------------------------------------------------------------
// 文件名 : MemPool.h
// 创建者 : magicTong
// 创建时间 : 2008-10-24 17:50:00
// 功能描述 : 一个简单的内存池实现
//
// $Id: $
// -----------------------------------------------------------------------*/
#ifndef __MEMPOOL_H__
#define __MEMPOOL_H__

// -------------------------------------------------------------------------
#include <queue>

#define MemoryBlockSize 1024
#define MemoryBlockNum 20

class KMemPool
{
public:
// 构造
explicit KMemPool(int a_memoryBlockNum = MemoryBlockNum,
int a_memoryBlockSize = MemoryBlockSize);
// 析构
virtual ~KMemPool();

// 两个主要的操作
int NewMemBuf(char*& a_recvBuff);
int DelMemBuf(char* a_recvBuff);

private:
void _initMemPool(int a_memoryBlockNum, int a_memoryBlockSize);

std::queue<char*> m_memPool;
};

// -------------------------------------------------------------------------
// $Log: $

#endif /* __MEMPOOL_H__ */

实现:

/* -------------------------------------------------------------------------
// 文件名 : MemPool.cpp
// 创建者 : magicTong
// 创建时间 : 2008-10-24 17:50:19
// 功能描述 : 简单内存池实现
//
// $Id: $
// -----------------------------------------------------------------------*/

#include "stdafx.h"
#include "MemPool.h"

// -------------------------------------------------------------------------

// 构造
KMemPool::KMemPool(int a_memoryBlockNum /* = MemoryBlockNum */,
int a_memoryBlockSize /* = MemoryBlockSize */)
{
_initMemPool(a_memoryBlockNum, a_memoryBlockSize);
}

// 析构
KMemPool::~KMemPool()
{
char* l_tempBuff = NULL;
while(!m_memPool.empty())
{
l_tempBuff = m_memPool.front();
m_memPool.pop();
if(l_tempBuff )
{
// 回收
delete[] l_tempBuff;
l_tempBuff = NULL;
}
}
}

// -------------------------------------------------------------------------
// 函数 : KMemPool::_initMemPool
// 功能 :
// 返回值 : void
// 参数 : int a_memoryBlockNum
// 参数 : int a_memoryBlockSize
// 附注 :
// -------------------------------------------------------------------------
void KMemPool::_initMemPool(int a_memoryBlockNum, int a_memoryBlockSize)
{
for(int i = 0; i < a_memoryBlockNum; ++i)
{
char* l_tempBuff = new char[a_memoryBlockSize];
if(l_tempBuff == NULL)
continue;

m_memPool.push(l_tempBuff);
}

}

// -------------------------------------------------------------------------
// 函数 : KMemPool::NewMemBuf
// 功能 : 申请一块内存,如果内存池空了,这个时候应该再像系统申请,并且在
// 类初始化的时候,加一个增量的变量,也可以提供这样的接口,这里为
// 了简单就没有这么做了,只是为了说明问题而已。
// 返回值 : int
// 参数 : char*& a_memoryBuff
// 附注 : 如果成功返回0,如果失败返回-1
// -------------------------------------------------------------------------
int KMemPool::NewMemBuf(char*& a_memoryBuff)
{
// 如果内存池已空,这个时候正确的做法应该是
// 重新申请大块内存
if (m_memPool.empty())
{
_initMemPool(MemoryBlockNum, MemoryBlockSize);
}

a_memoryBuff = m_memPool.front();
m_memPool.pop();
if(a_memoryBuff == NULL)
return -1;

return 0;
}

// -------------------------------------------------------------------------
// 函数 : KMemPool::DelMemBuf
// 功能 : 回收内存,将其放回队列中
// 返回值 : int
// 参数 : char* a_memoryBuff
// 附注 :
// -------------------------------------------------------------------------
int KMemPool::DelMemBuf(char* a_memoryBuff)
{
m_memPool.push(a_memoryBuff);
return 0;
}
// -------------------------------------------------------------------------
// $Log: $

根据《C++应用程序性能优化》实现代码如下:

/* -------------------------------------------------------------------------
// 文件名 : MemPoolEx.h
// 创建者 : magicTong
// 创建时间 : 2008-10-24 17:49:33
// 功能描述 :
//
// $Id: $
// -----------------------------------------------------------------------*/
#ifndef __MEMPOOLEX_H__
#define __MEMPOOLEX_H__

// -------------------------------------------------------------------------
#include <Windows.h>
#define MEMPOOL_ALIGNMENT 4

class KMemBlock
{
public:
KMemBlock(USHORT nTypes = 1, USHORT nUnitSize = 0);
virtual ~KMemBlock();

void operator delete(void *p, size_t);
void * operator new (size_t, USHORT nTypes, USHORT nUnitSize);

public:
USHORT nSize; // 内存块的大小 每个小块所占内存*小块个数
USHORT nFree; // 空闲块数
USHORT nFirst; // 第一个空闲块
//USHORT nDummyAlign1;
KMemBlock *pNext; // 下一个Block
char aData[1]; // 数据的初始位置

};

class KMemPoolEx
{
public:
KMemPoolEx(USHORT uUnitSize, USHORT uInitSize, USHORT uGrowSize);
virtual ~KMemPoolEx();

void* Alloc();
void Free(void* pFree);

private:
void _FreeMemeoryBlock(KMemBlock* pMyBlock);

KMemBlock* pBlock; // 第一个block的指针
USHORT nUnitSize; // 每个小内存块的字节数
USHORT nInitSize; // 初始的Block的内存块数目
USHORT nGrowSize; // 增加的Block的内存块数目
};
// -------------------------------------------------------------------------
// $Log: $

#endif /* __MEMPOOLEX_H__ */

实现部分:

/* -------------------------------------------------------------------------
// 文件名 : MemPoolEx.cpp
// 创建者 : magicTong
// 创建时间 : 2008-10-24 17:49:45
// 功能描述 :
//
// $Id: $
// -----------------------------------------------------------------------*/

#include "stdafx.h"
#include "MemPoolEx.h"

// -------------------------------------------------------------------------
// 构造
KMemBlock::KMemBlock (USHORT nTypes, USHORT nUnitSize)
{
nFree = nTypes - 1;
pNext = NULL;
nSize = nTypes * nUnitSize;
nFirst = 1;

char* pData = aData;
for(USHORT i = 1; i < nTypes; i++)
{
*(USHORT *)pData = i;
pData += nUnitSize;
}
}

// 析构
KMemBlock::~KMemBlock()
{
}

// -------------------------------------------------------------------------
// 函数 : KMemBlock::operator new
// 功能 :
// 返回值 : void *
// 参数 : size_t
// 参数 : USHORT nTypes
// 参数 : USHORT nUnitSize
// 附注 :
// -------------------------------------------------------------------------
void * KMemBlock::operator new(size_t, USHORT nTypes, USHORT nUnitSize)
{
return ::operator new (sizeof(KMemBlock) + nTypes * nUnitSize);
}

// -------------------------------------------------------------------------
// 函数 : KMemBlock::operator delete
// 功能 :
// 返回值 : void
// 参数 : void *p
// 参数 : size_t
// 附注 :
// -------------------------------------------------------------------------
void KMemBlock::operator delete(void *p, size_t)
{
::operator delete (p);
}

// -------------------------------------------------------------------------
// 线程池定义
// -------------------------------------------------------------------------
// 构造
// _uUnitSize 每个小内存块的字节数
// _uInitSize 是初始的Block的内存块数目
// _uGrowSize 增加的Block的内存块数目
KMemPoolEx::KMemPoolEx(USHORT _uUnitSize, USHORT _uInitSize, USHORT _uGrowSize)
{
pBlock = NULL;
nInitSize = _uInitSize;
nGrowSize = _uGrowSize;

if(_uUnitSize <= 2)
nUnitSize = 2;
else if(_uUnitSize > 2 && _uUnitSize <= 4)
nUnitSize = 4;
else
{
if(_uUnitSize % MEMPOOL_ALIGNMENT == 0)
nUnitSize = _uUnitSize;
else
nUnitSize = (_uUnitSize / MEMPOOL_ALIGNMENT + 1) * MEMPOOL_ALIGNMENT;
}
}

// 析构
KMemPoolEx::~KMemPoolEx()
{
KMemBlock* pMyBlock = pBlock;
if(pBlock)
_FreeMemeoryBlock(pMyBlock);
}

// -------------------------------------------------------------------------
// 函数 : KMemPool::_FreeMemeoryBlock
// 功能 : 递归释放内存
// 返回值 : void
// 参数 : KMemBlock *pMyBlock
// 附注 : 其实这个地方没必要使用递归,迭代实现很容易
// -------------------------------------------------------------------------
void KMemPoolEx::_FreeMemeoryBlock(KMemBlock *pMyBlock)
{
if(pMyBlock->pNext)
_FreeMemeoryBlock(pMyBlock->pNext);

delete pMyBlock;
}

// -------------------------------------------------------------------------
// 函数 : KMemPoolEx::Alloc
// 功能 : 申请内存
// 返回值 : void*
// 附注 :
// -------------------------------------------------------------------------
void* KMemPoolEx::Alloc()
{
if(!pBlock)
{
// 如果是第一次申请
pBlock = new (nInitSize, nUnitSize) KMemBlock(nInitSize, nUnitSize);
return pBlock->aData;
}

// 如果不是第一次申请
KMemBlock *pMyBlock = pBlock;
while(pMyBlock && !pMyBlock->nFree)
pMyBlock = pMyBlock->pNext;

//接下来的两种情况:1.找到有空闲块的block 2.找不到
void *retval;

// 找到了空闲块
if(pMyBlock)
{
pMyBlock->nFree--;
retval = pMyBlock->aData + nUnitSize * pMyBlock->nFirst;
pMyBlock->nFirst = *((USHORT*)retval);
return retval;
}
// 没有找到空闲块,要重新申请
else
{
if(!nGrowSize)
return NULL;
KMemBlock* newBlock = new (nGrowSize, nUnitSize) KMemBlock(nGrowSize, nUnitSize);
if(!newBlock)
return NULL;
newBlock->pNext = pBlock;
pBlock = newBlock;
return (void*)(newBlock->aData);
}

return NULL;
}

// -------------------------------------------------------------------------
// 函数 : KMemPoolEx::Free
// 功能 : 释放内存
// 返回值 : void
// 参数 : void* pFree
// 附注 : 释放内存时,并不真正的归还给堆,而且是回收到内存池中
// -------------------------------------------------------------------------
void KMemPoolEx::Free(void* pFree)
{
KMemBlock* pMyBlock = pBlock;
KMemBlock* pPreBlock = NULL; //pMyBlock指向Block的前一个Block,用于设置pNext

// 如果要求释放的内存并不是内存池里面的内存,则直接返回,不予释放
while((ULONG)pFree < (ULONG)pMyBlock->aData || (ULONG)pFree > (ULONG)(pMyBlock->aData + pMyBlock->nSize))
{
pPreBlock = pMyBlock;
pMyBlock = pMyBlock->pNext;

if(!pMyBlock)
return;
}

// 是内存池里面分配出去的,回收到内存池,并不真正归还给堆
if(pMyBlock)
{
pMyBlock->nFree++;
*((USHORT*)pFree) = pMyBlock->nFirst;
pMyBlock->nFirst = (USHORT)(((ULONG)pFree - (ULONG)pMyBlock->aData) / nUnitSize);

if(pMyBlock->nFree * nUnitSize == pMyBlock->nSize) //如果全是自由块
{
if(!pMyBlock->pNext) //如果这是最后一个block,则将其释放
{
delete pMyBlock; //释放
if(pPreBlock)
pPreBlock->pNext = NULL; //设置上一块的pNext指向NULL
else
pBlock = NULL;
}

}
}
}

// -------------------------------------------------------------------------
// $Log: $

数据库连接池是因为,初始化一个数据库连接是非常消耗系统资源的,因此就在程序开始阶段进行数据库的批量连接,然后把这些连接保存下来,等到要使用的时候才拿出来使用,使用完了再放入连接池中。了解不深就不多说了。

参考资料:

CSDN博客:许式伟 著 内存池(MemPool)技术详解 http://blog.csdn.net/xushiweizh/archive/2006/11/22/1402967.aspx

IBM技术文档:内存池 http://www.ibm.com/developerworks/cn/linux/l-cn-ppp/index6.html?ca=drs-cn

Java中数据库连接池原理机制讲解:http://www.68design.net/Development/JSP/20703-1.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: