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

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

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

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

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

  1. /* -------------------------------------------------------------------------
  2. //  文件名     :   KThreadPool.h
  3. //  创建者     :   magicTong
  4. //  创建时间    :   2008-10-23 15:02:31
  5. //  功能描述    :   线程池声明
  6. //
  7. //  $Id: $
  8. // -----------------------------------------------------------------------*/
  9. #ifndef __KTHREADPOOL_H__
  10. #define __KTHREADPOOL_H__
  11. // -------------------------------------------------------------------------
  12. #include <windows.h>
  13. #include <list>
  14. using namespace std;
  15. // 线程函数指针定义
  16. typedef DWORD (WINAPI *PTHREAD_FUNC_EX)(LPVOID lpThreadParameter);
  17. // 线程状态枚举
  18. typedef enum _enumKThreadStatus
  19. {
  20. THREADRUN,      // 运行
  21. THREADPAUSE,    // 暂停
  22. }
  23. KThreadStatus;
  24. // -------------------------------------------------------------------------
  25. // 类名       : KThread
  26. // 功能       : 线程类,可动态更换执行函数
  27. // 附注       :
  28. // -------------------------------------------------------------------------
  29. class KThread
  30. {
  31. public:
  32. // 构造
  33. KThread();
  34. // 析构
  35. ~KThread();
  36. // -------------------------------------------------------------------------
  37. // 函数       : Init
  38. // 功能       : 初始化函数
  39. // 返回值  : bool
  40. // 附注       :
  41. // -------------------------------------------------------------------------
  42. bool Init();
  43. // -------------------------------------------------------------------------
  44. // 函数       : Run
  45. // 功能       : 运行线程
  46. // 返回值  : bool
  47. // 附注       :
  48. // -------------------------------------------------------------------------
  49. bool Run();
  50. // -------------------------------------------------------------------------
  51. // 函数       : Pause
  52. // 功能       : 暂停线程
  53. // 返回值  : bool
  54. // 附注       :
  55. // -------------------------------------------------------------------------
  56. bool Pause();
  57. // -------------------------------------------------------------------------
  58. // 函数       : Join
  59. // 功能       : 调用Join的线程将阻塞,直到该线程执行完毕
  60. // 返回值  : void
  61. // 附注       :
  62. // -------------------------------------------------------------------------
  63. void Join();
  64. // -------------------------------------------------------------------------
  65. // 函数       : SetProc
  66. // 功能       : 设置线程运行的函数,和要传给线程的参数
  67. // 返回值  : void
  68. // 参数       : PTHREAD_FUNC_EX proc
  69. // 参数       : void* lpParam
  70. // 附注       :
  71. // -------------------------------------------------------------------------
  72. void SetProc(PTHREAD_FUNC_EX proc, void* lpParam);
  73. protected:
  74. KThread(KThread&){}
  75. // 线程实际运行的函数
  76. static DWORD WINAPI RealThreadProc(void* lpParam);
  77. friend class KThreadPool;
  78. protected:
  79. struct KThreadParam
  80. {
  81. PTHREAD_FUNC_EX proc;   // 用户线程函数
  82. void *lpParam;          // 用户线程参数
  83. KThread *pThread;       // 线程类对象
  84. };
  85. HANDLE              m_hThread;
  86. DWORD               m_id;
  87. KThreadParam        m_param;
  88. KThreadStatus       m_status;
  89. HANDLE              m_hEvt;
  90. HANDLE              m_hMtx;
  91. };
  92. // -------------------------------------------------------------------------
  93. // 类名       : KThreadPool
  94. // 功能       : 线程池类声明
  95. // 附注       :
  96. // -------------------------------------------------------------------------
  97. class KThreadPool
  98. {
  99. public:
  100. //构造,initNum初始情况线程数量
  101. KThreadPool(int initNum);
  102. //析构
  103. ~KThreadPool();
  104. // -------------------------------------------------------------------------
  105. // 函数       : DoWork
  106. // 功能       : 申请线程进行工作,proc工作函数,lpParam工作函数参数,run是否立即运行,返回线程ID
  107. // 返回值  : DWORD
  108. // 参数       : PTHREAD_FUNC_EX proc
  109. // 参数       : void *lpParam
  110. // 参数       : bool run = true
  111. // 附注       :
  112. // -------------------------------------------------------------------------
  113. DWORD DoWork(PTHREAD_FUNC_EX proc, void *lpParam, bool run = true);
  114. // -------------------------------------------------------------------------
  115. // 函数       : Run
  116. // 功能       : 运行线程,id线程ID
  117. // 返回值  : bool
  118. // 参数       : DWORD id
  119. // 附注       :
  120. // -------------------------------------------------------------------------
  121. bool Run(DWORD id);
  122. // -------------------------------------------------------------------------
  123. // 函数       : Pause
  124. // 功能       : 暂停运行线程,id线程ID
  125. // 返回值  : bool
  126. // 参数       : DWORD id
  127. // 附注       :
  128. // -------------------------------------------------------------------------
  129. bool Pause(DWORD id);
  130. //调整线程池大小为size,返回调整后线程池大小
  131. unsigned SetSize(unsigned size);
  132. protected:
  133. list<KThread*> m_lst;
  134. };

实现:

  1. /* -------------------------------------------------------------------------
  2. //  文件名     :   KThreadPool.cpp
  3. //  创建者     :   magicTong
  4. //  创建时间    :   2008-10-23 15:02:22
  5. //  功能描述    :   线程池定义
  6. //
  7. //  $Id: $
  8. // -----------------------------------------------------------------------*/
  9. #include "stdafx.h"
  10. #include "KThreadPool.h"
  11. // -------------------------------------------------------------------------
  12. // -------------------------------------------------------------------------
  13. // KThread类定义开始
  14. // -------------------------------------------------------------------------
  15. KThread::KThread(): m_hThread(NULL),
  16. m_status(THREADPAUSE),
  17. m_hEvt(0),
  18. m_hMtx(0)
  19. {
  20. }
  21. KThread::~KThread()
  22. {
  23. ::CloseHandle(m_hMtx);
  24. if (::TerminateThread(m_hThread, -1) == 0)
  25. return;
  26. }
  27. bool KThread::Init()
  28. {
  29. m_hThread = ::CreateThread(
  30. 0,
  31. 0,
  32. (PTHREAD_FUNC_EX)(KThread::RealThreadProc),
  33. (void*)&m_param,
  34. CREATE_SUSPENDED,
  35. &m_id);
  36. // 创建线程失败
  37. if (NULL == m_hThread)
  38. {
  39. return false;
  40. }
  41. m_param.proc = NULL;
  42. m_param.lpParam = NULL;
  43. m_param.pThread = this;
  44. //自动复位
  45. m_hEvt = ::CreateEvent(0, FALSE, FALSE, 0);
  46. if (m_hEvt == 0)
  47. {
  48. ::CloseHandle(m_hThread);
  49. return false;
  50. }
  51. m_hMtx = ::CreateMutex(0, 0, 0);
  52. if (m_hMtx == 0)
  53. {
  54. ::CloseHandle(m_hEvt);
  55. ::CloseHandle(m_hThread);
  56. return false;
  57. }
  58. return true;
  59. }
  60. bool KThread::Run()
  61. {
  62. ::WaitForSingleObject(m_hMtx, INFINITE);
  63. if (m_status == THREADPAUSE)
  64. if (::ResumeThread(m_hThread) == -1)
  65. {
  66. ::ReleaseMutex(m_hMtx);
  67. return false;
  68. }
  69. m_status = THREADRUN;
  70. ::ReleaseMutex(m_hMtx);
  71. return true;
  72. }
  73. bool KThread::Pause()
  74. {
  75. ::WaitForSingleObject(m_hMtx, INFINITE);
  76. if (m_status == THREADRUN)
  77. if (::SuspendThread(m_hThread) == -1)
  78. {
  79. ::ReleaseMutex(m_hMtx);
  80. return false;
  81. }
  82. m_status = THREADPAUSE;
  83. ::ReleaseMutex(m_hMtx);
  84. return true;
  85. }
  86. void KThread::Join()
  87. {
  88. ::WaitForSingleObject(m_hEvt, INFINITE);
  89. }
  90. void KThread::SetProc(PTHREAD_FUNC_EX proc, void* lpParam)
  91. {
  92. ::WaitForSingleObject(m_hMtx, INFINITE);
  93. m_param.proc = proc;
  94. m_param.lpParam = lpParam;
  95. ::ReleaseMutex(m_hMtx);
  96. }
  97. DWORD WINAPI KThread::RealThreadProc(void* lpParam)
  98. {
  99. PTHREAD_FUNC_EX proc;
  100. KThreadParam *pp = (KThreadParam*)lpParam;
  101. while (true)
  102. {
  103. proc = pp->proc;
  104. if (proc)
  105. (*proc)(pp->lpParam);
  106. pp->proc = NULL;
  107. pp->lpParam = NULL;
  108. pp->pThread->Pause();
  109. ::SetEvent(pp->pThread->m_hEvt);
  110. }
  111. }
  112. // -------------------------------------------------------------------------
  113. // KThread类定义结束
  114. // -------------------------------------------------------------------------
  115. // -------------------------------------------------------------------------
  116. // KThreadPool类定义开始
  117. // -------------------------------------------------------------------------
  118. KThreadPool::KThreadPool(int initNum)
  119. {
  120. KThread *pt;
  121. for (int i = 0; i < initNum; i++)
  122. {
  123. pt = new KThread;
  124. if (pt->Init())
  125. m_lst.push_back(pt);
  126. }
  127. }
  128. KThreadPool::~KThreadPool()
  129. {
  130. list<KThread*>::iterator itBegin = m_lst.begin();
  131. list<KThread*>::iterator itEnd = m_lst.end();
  132. for ( ; itBegin != itEnd; itBegin++)
  133. {
  134. delete (*itBegin);
  135. }
  136. }
  137. DWORD KThreadPool::DoWork(LPTHREAD_START_ROUTINE proc, void *lpParam, bool run)
  138. {
  139. list<KThread*>::iterator itBegin = m_lst.begin();
  140. list<KThread*>::iterator itEnd = m_lst.end();
  141. for (; itBegin != itEnd; itBegin++)
  142. {
  143. if ((*itBegin)->m_param.proc == NULL && (*itBegin)->m_status == THREADPAUSE)
  144. {
  145. (*itBegin)->SetProc(proc, lpParam);
  146. // 立即运行
  147. if (run)
  148. (*itBegin)->Run();
  149. return (*itBegin)->m_id;
  150. }
  151. }
  152. // 没有空闲线程,新建一个新的线程,加入链表
  153. KThread *pt = new KThread;
  154. if (pt->Init())
  155. m_lst.push_back(pt);
  156. pt->SetProc(proc, lpParam);
  157. if (run)
  158. pt->Run();
  159. return pt->m_id;
  160. }
  161. bool KThreadPool::Run(DWORD id)
  162. {
  163. list<KThread*>::iterator itBegin = m_lst.begin();
  164. list<KThread*>::iterator itEnd = m_lst.end();
  165. for (; itBegin != itEnd; itBegin++)
  166. {
  167. if ((*itBegin)->m_id == id)
  168. return ((*itBegin)->Run());
  169. }
  170. return false;
  171. }
  172. bool KThreadPool::Pause(DWORD id)
  173. {
  174. list<KThread*>::iterator itBegin = m_lst.begin();
  175. list<KThread*>::iterator itEnd = m_lst.end();
  176. for (; itBegin != itEnd; itBegin++)
  177. {
  178. if ((*itBegin)->m_id == id)
  179. return ((*itBegin)->Pause());
  180. }
  181. return false;
  182. }
  183. // -------------------------------------------------------------------------
  184. // 函数       : KThreadPool::SetSize
  185. // 功能       : 修改线程池的大小
  186. // 返回值  : unsigned
  187. // 参数       : unsigned size
  188. // 附注       : 如果小缩小线程池大小,谨慎使用
  189. // -------------------------------------------------------------------------
  190. unsigned KThreadPool::SetSize(unsigned size)
  191. {
  192. unsigned nowsize = m_lst.size();
  193. if (nowsize <= size)
  194. {
  195. KThread *pt;
  196. unsigned inc = size - nowsize;
  197. for (unsigned i = 0; i < inc; i++)
  198. {
  199. pt = new KThread;
  200. if (pt->Init())
  201. {
  202. m_lst.push_back(pt);
  203. }
  204. }
  205. return size;
  206. }
  207. else
  208. {
  209. unsigned dec = nowsize - size;
  210. list<KThread*>::iterator it = m_lst.begin();
  211. list<KThread*>::iterator ite = m_lst.end();
  212. list<KThread*>::iterator itemp;
  213. unsigned i = 0;
  214. for (; it != ite && i < dec;)
  215. {
  216. if ((*it)->m_status == THREADPAUSE)
  217. {
  218. itemp = it++;
  219. delete ((*itemp));
  220. m_lst.erase(itemp);
  221. i++;
  222. continue;
  223. }
  224. it++;
  225. }
  226. ::Sleep(100 * i);
  227. return m_lst.size();
  228. }
  229. }
  230. // -------------------------------------------------------------------------
  231. // KThreadPool类定义结束
  232. // -------------------------------------------------------------------------

使用:

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

  1. DWORD WINAPI threadFunc(LPVOID lpThreadParam);
  2. void CKThreadPoolExDlg::OnBtnCreate()
  3. {
  4. static i = 0;
  5. if (!m_pThreadPool)
  6. {
  7. m_pThreadPool = new KThreadPool(1);
  8. }
  9. m_pThreadPool->DoWork(threadFunc, this, true);
  10. i++;
  11. if (i == 4)
  12. {
  13. m_pThreadPool->SetSize(10);
  14. }
  15. }
  16. void CKThreadPoolExDlg::DoSomething()
  17. {
  18. //MessageBox("O(∩_∩)O哈哈~");
  19. while (true)
  20. {
  21. ::EnterCriticalSection(&m_cs);
  22. DWORD id = GetCurrentThreadId();
  23. CString cstr;
  24. cstr.Format("线程 %d 正在运行...", id);
  25. m_listInfo.InsertItem(m_listInfo.GetItemCount(), cstr);
  26. ::LeaveCriticalSection(&m_cs);
  27. ::Sleep(400);
  28. }
  29. }
  30. DWORD WINAPI threadFunc(LPVOID lpThreadParam)
  31. {
  32. CKThreadPoolExDlg *pdlg = (CKThreadPoolExDlg *)lpThreadParam;
  33. pdlg->DoSomething();
  34. return 0;
  35. }

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

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

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

使用内存池的好处:

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

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

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

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

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

  1. /* -------------------------------------------------------------------------
  2. //  文件名     :   MemPool.h
  3. //  创建者     :   magicTong
  4. //  创建时间    :   2008-10-24 17:50:00
  5. //  功能描述    :  一个简单的内存池实现
  6. //
  7. //  $Id: $
  8. // -----------------------------------------------------------------------*/
  9. #ifndef __MEMPOOL_H__
  10. #define __MEMPOOL_H__
  11. // -------------------------------------------------------------------------
  12. #include <queue>
  13. #define  MemoryBlockSize    1024
  14. #define  MemoryBlockNum     20
  15. class KMemPool
  16. {
  17. public:
  18. // 构造
  19. explicit KMemPool(int a_memoryBlockNum = MemoryBlockNum,
  20. int a_memoryBlockSize = MemoryBlockSize);
  21. // 析构
  22. virtual ~KMemPool();
  23. // 两个主要的操作
  24. int NewMemBuf(char*& a_recvBuff);
  25. int DelMemBuf(char* a_recvBuff);
  26. private:
  27. void _initMemPool(int a_memoryBlockNum, int a_memoryBlockSize);
  28. std::queue<char*> m_memPool;
  29. };
  30. // -------------------------------------------------------------------------
  31. // $Log: $
  32. #endif /* __MEMPOOL_H__ */

实现:

  1. /* -------------------------------------------------------------------------
  2. //  文件名     :   MemPool.cpp
  3. //  创建者     :   magicTong
  4. //  创建时间    :   2008-10-24 17:50:19
  5. //  功能描述    :   简单内存池实现
  6. //
  7. //  $Id: $
  8. // -----------------------------------------------------------------------*/
  9. #include "stdafx.h"
  10. #include "MemPool.h"
  11. // -------------------------------------------------------------------------
  12. // 构造
  13. KMemPool::KMemPool(int a_memoryBlockNum /* = MemoryBlockNum */,
  14. int a_memoryBlockSize /* = MemoryBlockSize */)
  15. {
  16. _initMemPool(a_memoryBlockNum, a_memoryBlockSize);
  17. }
  18. // 析构
  19. KMemPool::~KMemPool()
  20. {
  21. char* l_tempBuff = NULL;
  22. while(!m_memPool.empty())
  23. {
  24. l_tempBuff = m_memPool.front();
  25. m_memPool.pop();
  26. if(l_tempBuff )
  27. {
  28. // 回收
  29. delete[] l_tempBuff;
  30. l_tempBuff = NULL;
  31. }
  32. }
  33. }
  34. // -------------------------------------------------------------------------
  35. // 函数       : KMemPool::_initMemPool
  36. // 功能       :
  37. // 返回值  : void
  38. // 参数       : int a_memoryBlockNum
  39. // 参数       : int a_memoryBlockSize
  40. // 附注       :
  41. // -------------------------------------------------------------------------
  42. void KMemPool::_initMemPool(int a_memoryBlockNum, int a_memoryBlockSize)
  43. {
  44. for(int i = 0; i < a_memoryBlockNum; ++i)
  45. {
  46. char* l_tempBuff = new char[a_memoryBlockSize];
  47. if(l_tempBuff == NULL)
  48. continue;
  49. m_memPool.push(l_tempBuff);
  50. }
  51. }
  52. // -------------------------------------------------------------------------
  53. // 函数       : KMemPool::NewMemBuf
  54. // 功能       : 申请一块内存,如果内存池空了,这个时候应该再像系统申请,并且在
  55. //            类初始化的时候,加一个增量的变量,也可以提供这样的接口,这里为
  56. //            了简单就没有这么做了,只是为了说明问题而已。
  57. // 返回值  : int
  58. // 参数       : char*& a_memoryBuff
  59. // 附注       : 如果成功返回0,如果失败返回-1
  60. // -------------------------------------------------------------------------
  61. int KMemPool::NewMemBuf(char*& a_memoryBuff)
  62. {
  63. // 如果内存池已空,这个时候正确的做法应该是
  64. // 重新申请大块内存
  65. if (m_memPool.empty())
  66. {
  67. _initMemPool(MemoryBlockNum, MemoryBlockSize);
  68. }
  69. a_memoryBuff = m_memPool.front();
  70. m_memPool.pop();
  71. if(a_memoryBuff == NULL)
  72. return -1;
  73. return 0;
  74. }
  75. // -------------------------------------------------------------------------
  76. // 函数       : KMemPool::DelMemBuf
  77. // 功能       : 回收内存,将其放回队列中
  78. // 返回值  : int
  79. // 参数       : char* a_memoryBuff
  80. // 附注       :
  81. // -------------------------------------------------------------------------
  82. int KMemPool::DelMemBuf(char* a_memoryBuff)
  83. {
  84. m_memPool.push(a_memoryBuff);
  85. return 0;
  86. }
  87. // -------------------------------------------------------------------------
  88. // $Log: $

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

  1. /* -------------------------------------------------------------------------
  2. //  文件名     :   MemPoolEx.h
  3. //  创建者     :   magicTong
  4. //  创建时间    :   2008-10-24 17:49:33
  5. //  功能描述    :
  6. //
  7. //  $Id: $
  8. // -----------------------------------------------------------------------*/
  9. #ifndef __MEMPOOLEX_H__
  10. #define __MEMPOOLEX_H__
  11. // -------------------------------------------------------------------------
  12. #include <Windows.h>
  13. #define MEMPOOL_ALIGNMENT 4
  14. class KMemBlock
  15. {
  16. public:
  17. KMemBlock(USHORT nTypes = 1, USHORT nUnitSize = 0);
  18. virtual ~KMemBlock();
  19. void  operator delete(void *p, size_t);
  20. void * operator new (size_t, USHORT nTypes, USHORT nUnitSize);
  21. public:
  22. USHORT          nSize;              // 内存块的大小  每个小块所占内存*小块个数
  23. USHORT          nFree;              // 空闲块数
  24. USHORT          nFirst;             // 第一个空闲块
  25. //USHORT          nDummyAlign1;
  26. KMemBlock       *pNext;             // 下一个Block
  27. char            aData[1];           // 数据的初始位置
  28. };
  29. class KMemPoolEx
  30. {
  31. public:
  32. KMemPoolEx(USHORT uUnitSize, USHORT uInitSize, USHORT uGrowSize);
  33. virtual ~KMemPoolEx();
  34. void* Alloc();
  35. void Free(void* pFree);
  36. private:
  37. void _FreeMemeoryBlock(KMemBlock* pMyBlock);
  38. KMemBlock*      pBlock;         // 第一个block的指针
  39. USHORT          nUnitSize;      // 每个小内存块的字节数
  40. USHORT          nInitSize;      // 初始的Block的内存块数目
  41. USHORT          nGrowSize;      // 增加的Block的内存块数目
  42. };
  43. // -------------------------------------------------------------------------
  44. // $Log: $
  45. #endif /* __MEMPOOLEX_H__ */

实现部分:

  1. /* -------------------------------------------------------------------------
  2. //  文件名     :   MemPoolEx.cpp
  3. //  创建者     :   magicTong
  4. //  创建时间    :   2008-10-24 17:49:45
  5. //  功能描述    :
  6. //
  7. //  $Id: $
  8. // -----------------------------------------------------------------------*/
  9. #include "stdafx.h"
  10. #include "MemPoolEx.h"
  11. // -------------------------------------------------------------------------
  12. // 构造
  13. KMemBlock::KMemBlock (USHORT nTypes, USHORT nUnitSize)
  14. {
  15. nFree = nTypes - 1;
  16. pNext = NULL;
  17. nSize = nTypes * nUnitSize;
  18. nFirst = 1;
  19. char* pData = aData;
  20. for(USHORT i = 1; i < nTypes; i++)
  21. {
  22. *(USHORT *)pData = i;
  23. pData += nUnitSize;
  24. }
  25. }
  26. // 析构
  27. KMemBlock::~KMemBlock()
  28. {
  29. }
  30. // -------------------------------------------------------------------------
  31. // 函数       : KMemBlock::operator new
  32. // 功能       :
  33. // 返回值  : void *
  34. // 参数       : size_t
  35. // 参数       : USHORT nTypes
  36. // 参数       : USHORT nUnitSize
  37. // 附注       :
  38. // -------------------------------------------------------------------------
  39. void * KMemBlock::operator new(size_t, USHORT nTypes, USHORT nUnitSize)
  40. {
  41. return ::operator new (sizeof(KMemBlock) + nTypes * nUnitSize);
  42. }
  43. // -------------------------------------------------------------------------
  44. // 函数       : KMemBlock::operator delete
  45. // 功能       :
  46. // 返回值  : void
  47. // 参数       : void *p
  48. // 参数       : size_t
  49. // 附注       :
  50. // -------------------------------------------------------------------------
  51. void  KMemBlock::operator delete(void *p, size_t)
  52. {
  53. ::operator delete (p);
  54. }
  55. // -------------------------------------------------------------------------
  56. // 线程池定义
  57. // -------------------------------------------------------------------------
  58. // 构造
  59. // _uUnitSize 每个小内存块的字节数
  60. // _uInitSize 是初始的Block的内存块数目
  61. // _uGrowSize 增加的Block的内存块数目
  62. KMemPoolEx::KMemPoolEx(USHORT _uUnitSize, USHORT _uInitSize, USHORT _uGrowSize)
  63. {
  64. pBlock = NULL;
  65. nInitSize = _uInitSize;
  66. nGrowSize = _uGrowSize;
  67. if(_uUnitSize <= 2)
  68. nUnitSize = 2;
  69. else if(_uUnitSize > 2 && _uUnitSize <= 4)
  70. nUnitSize = 4;
  71. else
  72. {
  73. if(_uUnitSize % MEMPOOL_ALIGNMENT == 0)
  74. nUnitSize = _uUnitSize;
  75. else
  76. nUnitSize = (_uUnitSize / MEMPOOL_ALIGNMENT + 1) * MEMPOOL_ALIGNMENT;
  77. }
  78. }
  79. // 析构
  80. KMemPoolEx::~KMemPoolEx()
  81. {
  82. KMemBlock* pMyBlock = pBlock;
  83. if(pBlock)
  84. _FreeMemeoryBlock(pMyBlock);
  85. }
  86. // -------------------------------------------------------------------------
  87. // 函数       : KMemPool::_FreeMemeoryBlock
  88. // 功能       : 递归释放内存
  89. // 返回值  : void
  90. // 参数       : KMemBlock *pMyBlock
  91. // 附注       : 其实这个地方没必要使用递归,迭代实现很容易
  92. // -------------------------------------------------------------------------
  93. void KMemPoolEx::_FreeMemeoryBlock(KMemBlock *pMyBlock)
  94. {
  95. if(pMyBlock->pNext)
  96. _FreeMemeoryBlock(pMyBlock->pNext);
  97. delete pMyBlock;
  98. }
  99. // -------------------------------------------------------------------------
  100. // 函数       : KMemPoolEx::Alloc
  101. // 功能       : 申请内存
  102. // 返回值  : void*
  103. // 附注       :
  104. // -------------------------------------------------------------------------
  105. void* KMemPoolEx::Alloc()
  106. {
  107. if(!pBlock)
  108. {
  109. // 如果是第一次申请
  110. pBlock = new (nInitSize, nUnitSize) KMemBlock(nInitSize, nUnitSize);
  111. return pBlock->aData;
  112. }
  113. // 如果不是第一次申请
  114. KMemBlock *pMyBlock = pBlock;
  115. while(pMyBlock && !pMyBlock->nFree)
  116. pMyBlock = pMyBlock->pNext;
  117. //接下来的两种情况:1.找到有空闲块的block 2.找不到
  118. void *retval;
  119. // 找到了空闲块
  120. if(pMyBlock)
  121. {
  122. pMyBlock->nFree--;
  123. retval = pMyBlock->aData + nUnitSize * pMyBlock->nFirst;
  124. pMyBlock->nFirst = *((USHORT*)retval);
  125. return retval;
  126. }
  127. // 没有找到空闲块,要重新申请
  128. else
  129. {
  130. if(!nGrowSize)
  131. return NULL;
  132. KMemBlock* newBlock = new (nGrowSize, nUnitSize) KMemBlock(nGrowSize, nUnitSize);
  133. if(!newBlock)
  134. return NULL;
  135. newBlock->pNext = pBlock;
  136. pBlock = newBlock;
  137. return (void*)(newBlock->aData);
  138. }
  139. return NULL;
  140. }
  141. // -------------------------------------------------------------------------
  142. // 函数       : KMemPoolEx::Free
  143. // 功能       : 释放内存
  144. // 返回值  : void
  145. // 参数       : void* pFree
  146. // 附注       : 释放内存时,并不真正的归还给堆,而且是回收到内存池中
  147. // -------------------------------------------------------------------------
  148. void KMemPoolEx::Free(void* pFree)
  149. {
  150. KMemBlock* pMyBlock = pBlock;
  151. KMemBlock* pPreBlock = NULL;    //pMyBlock指向Block的前一个Block,用于设置pNext
  152. // 如果要求释放的内存并不是内存池里面的内存,则直接返回,不予释放
  153. while((ULONG)pFree < (ULONG)pMyBlock->aData || (ULONG)pFree > (ULONG)(pMyBlock->aData + pMyBlock->nSize))
  154. {
  155. pPreBlock = pMyBlock;
  156. pMyBlock = pMyBlock->pNext;
  157. if(!pMyBlock)
  158. return;
  159. }
  160. // 是内存池里面分配出去的,回收到内存池,并不真正归还给堆
  161. if(pMyBlock)
  162. {
  163. pMyBlock->nFree++;
  164. *((USHORT*)pFree) = pMyBlock->nFirst;
  165. pMyBlock->nFirst = (USHORT)(((ULONG)pFree - (ULONG)pMyBlock->aData) / nUnitSize);
  166. if(pMyBlock->nFree * nUnitSize == pMyBlock->nSize)   //如果全是自由块
  167. {
  168. if(!pMyBlock->pNext)  //如果这是最后一个block,则将其释放
  169. {
  170. delete pMyBlock;  //释放
  171. if(pPreBlock)
  172. pPreBlock->pNext = NULL;  //设置上一块的pNext指向NULL
  173. else
  174. pBlock = NULL;
  175. }
  176. }
  177. }
  178. }
  179. // -------------------------------------------------------------------------
  180. // $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

“池化技术”漫谈 - 线程池,内存池,连接池……相关推荐

  1. java构建内存池队列_池化技术(线程池、连接池、内存池等)

    一.池化技术 - 简单点来说,就是提前保存大量的资源,以备不时之需. 对于线程,内存,oracle的连接对象等等,这些都是资源,程序中当你创建一个线程或者在堆上申请一块内存时,都涉及到很多系统调用,也 ...

  2. 池化技术及jdk的线程池讲解

    概述 程序运行的本质是消耗系统资源,线程.数据库连接等都会耗费系统的资源.线程.数据库连接等的创建.销毁等都十分消耗系统资源,所以,如果使用池化技术(线程池.数据库连接池等),可以对系统资源进行控制和 ...

  3. 【池化技术】池化技术基础和原理

    文章目录 一.概念 二.应用 1. 线程池 2. 连接池 3.内存池 三.实例 一.概念 池化技术指的是提前准备一些资源,在需要时可以重复使用这些预先准备的资源. 在系统开发过程中,我们经常会用到池化 ...

  4. 深入研究池化技术——对象池

    池化技术 池化技术是性能调优的重要措施,池化的思想是把对象放到池子里,当要使用的时候,从池子里面拿对象,用完后再放回池子里,这样可以降低资源分配以及释放的开销,从而提升性能,在实际项目中,其实我们每天 ...

  5. 常见池化技术:连接池、线程池和内存池等

    这里主要说几种:连接池.线程池.内存池和异步请求池,下面依次做具体的介绍. 连接池 连接池,如客户端连接请求redis.mysql等,目的是为了可以做并发操作,以及对连接的复用,一般和多线程一起使用, ...

  6. 池化技术 java_netty4的内存池化技术

    此文已由作者徐赟授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 一. 前言 java语言在运行于JVM的前提下,内存分配和回收通常无需用户干预.用户创建对象时,系统会在堆中分 ...

  7. 一文详解java线程池 详解Java线程池的七个参数 详解池化技术 java如何选择核心线程数 详解Java线程池的拒绝策略

    目录 引言 线程池使用场景 加快请求响应(响应时间优先) 加快处理大任务(吞吐量优先) 特殊说明 线程池的池化技术 线程池的创建 手动创建 创建newFixedThreadPool线程池 创建newS ...

  8. 从源码分析线程池(池化技术)的实现原理

    线程池是一个非常重要的知识点,也是池化技术的一个典型应用,相信很多人都有使用线程池的经历,但是对于线程池的实现原理大家都了解吗?本篇文章我们将深入线程池源码来一探究竟. 线程池的起源 背景: 随着计算 ...

  9. 池化技术-数据库连接池

    池化技术-数据库连接池 简介 数据库连接池 什么是数据库连接池 长连接和连接池的区别 数据库连接池运行机制 连接池和线程池的关系 连接池的连接数量 数据库连接池的设计 设计思路 设计逻辑 构造函数 初 ...

最新文章

  1. 移动平均滤波_Kalman滤波理论与MATLAB实现引言
  2. 处理数字_4_计算某列的总和
  3. cmdb整体项目梳理(2)
  4. 再看lambda/sorted/filter/map
  5. linux安装ftp后账号密码设置,CentOS 建立ftp账号(vsftpd运用安装与配置疑问 )
  6. 在HTML中取得请求中的参数
  7. 数据分析师需要掌握哪方面的计算机技能?
  8. DevExpress之ChartControl用法
  9. mvp的全称_库里常规赛mvp是哪一年,分别于2014-15和2015-16赛季荣膺
  10. ear的英语怎么念_不一样的高阶美式英语视频字母表 - A到I
  11. Vue 开发在微信公众号中如何文件下载
  12. Linux rpm -ivm,PowerLinux 7R1项目实施手册PDF
  13. 宇宙代码与磁子计算机,新认识!宇宙产生什么最强磁铁?比人类产生的最强磁场强一亿倍...
  14. linux 移动硬盘 machine,MacBook使用一块移动硬盘做Win To Go及Time Machine备份
  15. python小白第一天:解决python不是内部或外部命令,也不是可运行的程序或批处理文件/sublime无法显示python结果问题
  16. 2023年软考信息安全工程师备考学习笔记汇总
  17. 【Python】Python之禅
  18. 干货 | 以模型为中心,携程契约系统的演进
  19. html SRC是source的简写
  20. 手机二要素-运营商二要素验证

热门文章

  1. 洛谷P6771 [USACO05MAR]Space Elevator 太空电梯
  2. 遍历字符串字符 php,php逐个汉字遍历字符串
  3. jarvis guestbook2 / level6_x64
  4. usb音频传输的优劣
  5. iMazing许可证编号如何激活苹果版手机管理器支持 Win / Mac 双平台
  6. android studio 连接 华为手机真机
  7. 内容型平台运营的底层逻辑方法论
  8. [CF913F]Strongly Connected Tournament
  9. EventSetter
  10. 2022年12月电子学会青少年软件编程Python(二级)等级考试真题解析