池化技术能够减少资源对象的创建次数,提高程序的响应性能,特别是在高并发下这种提高更加明显。
下面我们介绍两种常见的池化技术:连接池、线程池和内存池
连接池
数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成 一个连接池,由程序动态地对池中的连接进行申请,使用,释放。
优点
1. 资源复用 :由于数据库连接得到复用,避免了频繁的创建、释放连接引起的性能开销,在减少系统消耗的基础 上,另一方面也增进了系统运行环境的平稳性(减少内存碎片以及数据库临时进程/线程的数 量)。
2. 更快的系统响应速度: 数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池中备用。此时连接的初始化 工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了从数据库连接初始化和释 放过程的开销,从而缩减了系统整体响应时间。
3. 统一的连接管理,避免数据库连接泄露: 在较为完备的数据库连接池实现中,可根据预先的连接占用超时设定,强制收回被占用连接。从而 避免了常规数据库连接操作中可能出现的资源泄露。
连接池设计思路
1. 连接到数据库,涉及到数据库ip、端口、用户名、密码、数据库名字等;
1. 连接的操作,每个连接对象都是独立的连接通道,它们是独立的
2. 配置最小连接数和最大连接数
2. 需要一个队列管理他的连接,比如使用list;
3. 获取连接对象;
4. 归还连接对象;
5. 连接池的名
线程池
线程池是一种线程管理技术,它通过维护一个线程集合来执行任务,避免了频繁创建和销毁线程带来的高昂开销。线程池的核心思想是线程复用,即通过重复使用一组线程来处理多个任务。
优点
- 资源复用:线程池通过复用线程,避免了频繁创建和销毁线程带来的资源开销。
- 性能优化:减少了线程创建和销毁的时间,提高了任务执行的响应速度。
- 线程管理:通过限制线程的数量,避免系统因为线程数过多而导致的资源耗尽问题(如内存耗尽)。
- 任务调度:线程池提供了任务队列和任务调度机制,便于管理和执行大量任务。
线程池设计思路
- 预创建线程池:在初始化线程池时,可以预先创建一定数量的核心线程,减少任务提交时的延迟。
- 任务队列:通过任务队列管理待执行的任务,避免任务提交时因线程不足而阻塞。
- 线程复用:线程执行完任务后不会被销毁,而是返回线程池等待下一个任务,减少了线程的创建和销毁开销。
- 拒绝策略:提供多种任务拒绝策略,确保系统在高负载下仍能稳定运行。
- 动态调整:根据任务量和系统负载,动态调整线程池中线程的数量,优化资源使
内存池
内存池(Memory Pool)的设计和使用是一种内存管理技术,旨在提高内存分配和回收的效率,减少内存碎片,并优化程序的性能。内存池通过预先分配一块大内存区域,然后在该区域内进行小块内存的分配和释放,避免频繁调用系统的内存管理函数(如 malloc
和 free
)。
优点
-
减少内存碎片:内存池通过预先分配和管理大块内存,避免了频繁的小块内存分配和释放,从而减少了内存碎片。
-
提高内存分配效率:由于内存池提前分配了一大块内存,后续的分配和释放操作只需要在内存池内部进行,极大地提高了效率,尤其适用于高频率的内存分配和释放场景。
-
降低系统调用开销:内存池减少了对系统
malloc
和free
的调用次数,降低了系统调用的开销,提高了程序的整体性能。
内存池的设计思路
-
初始化内存池:向操作系统申请一大块内存,将其分割成多个固定大小的小块,并将这些小块链接成一个空闲列表。
-
分配内存:从空闲列表中取出一个内存块,并将空闲列表头指针指向下一个空闲块。返回取出的内存块给应用程序。
-
释放内存:将释放的内存块重新插入空闲列表的头部,便于后续分配。
-
内存池扩展:当内存池中的内存块全部被分配出去时,可以申请新的内存块,并将其加入到空闲列表中,从而动态扩展内存池。
连接池和线程池的区别
线程池:主动调用任务。当任务队列不为空的时候从队列取任务取执行。
比如去银行办理业务,窗口柜员是线程,多个窗口组成了线程池,柜员从排号队列叫号执行。
连接池:被动被任务使用。当某任务需要操作数据库时,只要从连接池中取出一个连接对象,当任 务使用完该连接对象后,将该连接对象放回到连接池中。如果连接池中没有连接对象可以用,那么 该任务就必须等待。
比如去银行用笔填单,笔是连接对象,我们要用笔的时候去取,用完了还回去。
连接池和线程池设置数量的关系:
一般线程池线程数量和连接池连接对象数量一致;
一般线程执行任务完毕的时候归还连接对象;