一、模式介绍
对象池模式可以归类为创建型模式,是预先创建若干对象然后保存到内存对象池中,等到程序需要使用对象的时候,直接从对象池中获取已经创建好的对象使用即可,免去了新建对象的巨大开销,节约的时间。同时,等到对象被使用完了,可以将其再次返回对象池中。
通常,在资源比较受限、对象创建销毁成本过高的时候可以考虑使用对象池模式。一般而言,对象池模式包含如下几种角色:
- 抽象对象,定义对象池中对象的行为;
- 具体对象,实现对象池中对象的行为;
- 对象池,持有对象并提供获取和返还等操作;
下面是对象池模式的通用实现代码:
public interface IPoolObject {
void operation();
}
@Slf4j
public class ConcretePoolObject implements IPoolObject{
@Override
public void operation() {
log.info("ConcretePoolObject operation!!!");
}
}
@Slf4j
public class ObjectPool {
/**
* 最小维持的对象数量
*/
private int minCount;
/**
* 最大维持的对象数量
*/
private int maxCount;
/**
* 需要线程安全
* 空闲中的对象池
*/
private Vector<IPoolObject> idleObjects;
/**
* 已被使用中的对象池
*/
private Vector<IPoolObject> busyObjects;
/**
* 递增步长
*/
public static final Integer INCREASE_STEP = 10;
public ObjectPool(int minCount, int maxCount){
this.minCount = minCount;
this.maxCount = maxCount;
this.idleObjects = new Vector<IPoolObject>();
this.busyObjects = new Vector<IPoolObject>();
// 初始只实例化最小数量个空闲对象
this.resizeIdleObjects(minCount);
}
/**
* 重置空闲池
* @param count 需要添加到空闲池中的对象个数
*/
private void resizeIdleObjects(int count){
for(int i=0;i<count;i++){
idleObjects.add(new ConcretePoolObject());
}
}
/**
* 归还对象
* @param object
*/
public void returnObject(IPoolObject object){
idleObjects.add(object);
if(busyObjects.contains(object)){
busyObjects.remove(object);
}
}
/**
* 从空闲池中取出一个对象
* @return
*/
public IPoolObject getObject() throws Exception {
IPoolObject poolObject = null;
if(idleObjects.size() > 0){
// 空闲池中尚有对象可以使用
poolObject = idleObjects.get(0);
idleObjects.remove(poolObject);
busyObjects.add(poolObject);
} else {
// 空闲池中已无可用对象
if(idleObjects.size() >= maxCount){
log.error("对象池中对象已达上限,无法再扩容!");
throw new Exception("对象池中对象已达上限,无法再扩容!");
}
// 空闲池进行扩容
int diffCount = maxCount - minCount;
resizeIdleObjects(diffCount > INCREASE_STEP ? INCREASE_STEP : diffCount);
poolObject = getObject();
}
return poolObject;
}
}
public class Main {
public static void main(String[] args) {
ObjectPool pool = new ObjectPool(3,8);
IPoolObject object = null;
try {
object = pool.getObject();
} catch (Exception e) {
e.printStackTrace();
}
object.operation();
}
}
二、使用案例
- 数据库连接池
- 线程池
三、模式总结
总的来说,对象池模式更像是单例模式和享元模式的混合体,对象池是单例的,对象池中对象则是共享的。
3.1 优点
- 省去创建和销毁对象需要的资源和时间开销;
3.2 缺点
- 并发场景下的处理比较复杂;
- 伸缩性问题会给对象池带来瓶颈;
- 很难合理设定对象池的大小,够用和浪费之间的平衡难以掌控;
网友评论