文章首先通过一个通俗的实例帮助读者理解池化思想,随后说明池化思想在各种技术中的体现。
(欢迎指正)
例子 - 为何要用池?
先举一个简单的使用篮球 例子,我们有多种策略使用篮球,并且使用篮球之后会产生一定的代价,主观上认为我们倾向于将代价最小化。
策略1:(一次性使用)
这是一种比较笨的策略,每次都买一个新的篮球用于使用,使用之后丢掉。于是我们可以得到如下代价公式:
策略2:(重复使用)
在该策略中,认为篮球是可以多次使用的。于是我们可以得到如下公式::
策略的选择
上面列举了两种策略,事实上还有很多其他的策略。
两种策略本身是没有绝对的好坏的,而是视场景而定的。但就现实情况而言(比如,使用次数很多),篮球这个例子中符合如下的规律:
这意味着,复用的总代价 小于 不复用的代价,即 复用的策略更适合篮球这个例子。
而策略2反映的就是一种池化的思想,“复用的代价”远远小于“创建的代价”,所以此处通过池化技术增加“复用”、减少“创建”。
PS:有些场景下 “创建的代价”远远小于 “复用的代价”,此时就应该采用策略1的方式了。
技术实例
结合上面提到的主要思想,分别看看在编程中实际用到的一些池技术。
对象池
对象创建的代价
这里我们主要以java为代表,在java中创建对象,主要包括如下几个步骤:
- 根据new 等标识符后面的参数,在常量池查找类的符号引用。
- 如果没找到符号应用(类并未加载),进行类的加载、解析、初始化等。
- 虚拟机根据类,为对象在堆中分配内存,并将分配的内存初始化为0。针对对象头,建立相应的描述结构。(耗时操作:需要查找堆中的空闲区域,修改内存分配状态等)
- 调用对象的初始化方法。(耗时操作:用户的复杂的逻辑验证等操作,如IO、数值计算是否符合规定等等)
对象池的优势
通过对象创建的例子,可看出对象创建是一个复杂的过程,少数的对象的创建并不会影响程序的太多的性能,但是如果达到了数以万计,就应该考虑复用同类对象的分配了。
【通俗理解】只是替换某个已存在对象的状态(填充原对象结构中的变量),复用已存在对象分配的内存(节省了寻找空闲堆区等方面的时间)。
(相当于给内存重新换了身衣服)这里认为,重新创建对象的代价 远远大于 更换已存在对象中相关的状态变量。
数据库连接池
更新中…
线程池
更新中…