前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java 对象池技术

java 对象池技术

作者头像
breezedancer
发布2018-09-12 15:44:36
2.1K0
发布2018-09-12 15:44:36
举报
文章被收录于专栏:技术与生活技术与生活

中断了一段时间,再次开始技术之旅;心里有个小目标,先把对象池技术梳理清楚。

1、为什么用对象池 在 java 中,对象的生命周期包括对象创建、对象使用,对象消失三个时间段,其中对象的使用是对象真正需要存活的时间,不好修改,该用的时候还得使用啊。对象的创建和消失就得好好控制下了。对象的创建是比较费时间的,也许感觉不到,好比一个赋值操作int i=1,也是需要耗时的,在比如构造一个对象,一个数组就更加消耗时间。再说对象的消除,在 java 里面使用 GC 来进行对象回收,其实也是需要对对象监控每一个运行状态,包括引用,赋值等。在 Full GC 的时候,会暂停其他操作,独占 CPU。所以,我们需要控制对象的创建数量,也不要轻易的让对象消失,让他的复用更加充分。

2、对象池

对象池其实就是一个集合,里面包含了我们需要的对象集合,当然这些对象都被池化了,也就是被对象池所管理,想要这样的对象,从池子里取个就行,但是用完得归还。对象池的对象最好是创建比较费时的大对象,如果是太简单的对象,再进入池化的时间比自己构建还多,就不划算了。可以理解对象池为单例模式的延展,多例模式,就那么几个对象实例,再多没有了。

3、自定义一个低质量的对象池

首先构造一个池化对象,也就是对实际对象封装下,为什么呢?当然是为了让对象池更好的管理

代码语言:javascript
复制
public class PooledObject {    private Object objection = null;// 外界使用的对象
    private boolean busy = false; // 此对象是否正在使用的标志,默认没有正在使用

    // 构造函数,池化对象
    public PooledObject(Object objection) {        this.objection = objection;
    }    // 返回此对象中的对象
    public Object getObject() {        return objection;
    }    // 设置此对象的,对象
    public void setObject(Object objection) {        this.objection = objection;
    }    // 获得对象对象是否忙
    public boolean isBusy() {        return busy;
    }    // 设置对象的对象正在忙
    public void setBusy(boolean busy) {        this.busy = busy;
    }
}

池化对象现在包括两个属性,一个是原始对象的引用,另外一个表示当前对象是否在使用

接下来把对象池写出来

代码语言:javascript
复制
import java.util.Enumeration;import java.util.Vector;public abstract class ObjectPool<T> {    public static int numObjects = 10; // 对象池的大小
    public static int maxObjects = 50; // 对象池最大的大小
    protected Vector<PooledObject<T>> objects = null; // 存放对象池中对象的向量(PooledObject类型)

    public ObjectPool() {
    }    /*** 创建一个对象池 ***/
    public synchronized void createPool() {        // 确保对象池没有创建。如果创建了,保存对象的向量 objects 不会为空
        if (objects != null) {            return; // 如果己经创建,则返回
        }        // 创建保存对象的向量 , 初始时有 0 个元素
         objects = new Vector<PooledObject<T>>();         for (int i = 0; i < numObjects; i++) {
                objects.addElement(create());
            }
    }    public abstract PooledObject<T> create();    public synchronized T getObject() {        // 确保对象池己被创建
        if (objects == null) {            return null; // 对象池还没创建,则返回 null
        }
        T t = getFreeObject(); // 获得一个可用的对象
        // 如果目前没有可以使用的对象,即所有的对象都在使用中
        while (t == null) {
            wait(250);
            t = getFreeObject(); // 重新再试,直到获得可用的对象,如果
            // getFreeObject() 返回的为 null,则表明创建一批对象后也不可获得可用对象
        }        return t;// 返回获得的可用的对象
    }    /**
     * 本函数从对象池对象 objects 中返回一个可用的的对象,如果 当前没有可用的对象,则创建几个对象,并放入对象池中。
     * 如果创建后,所有的对象都在使用中,则返回 null
     */
    private T getFreeObject() {        // 从对象池中获得一个可用的对象
        T obj = findFreeObject();        if (obj == null) {
            createObjects(10); // 如果目前对象池中没有可用的对象,创建一些对象
            // 重新从池中查找是否有可用对象
            obj = findFreeObject();            // 如果创建对象后仍获得不到可用的对象,则返回 null
            if (obj == null) {                return null;
            }
        }        return obj;
    }    public void createObjects(int increment){        for (int i = 0; i < increment; i++) {            if (objects.size() > maxObjects) {                return;
            }
            objects.addElement(create());
        }
    }    /**
     * 查找对象池中所有的对象,查找一个可用的对象, 如果没有可用的对象,返回 null
     */
    private T findFreeObject() {
        T obj = null;
        PooledObject<T> pObj = null;        // 获得对象池向量中所有的对象
        Enumeration<PooledObject<T>> enumerate = objects.elements();        // 遍历所有的对象,看是否有可用的对象
        while (enumerate.hasMoreElements()) {
            pObj = (PooledObject<T>) enumerate.nextElement();            // 如果此对象不忙,则获得它的对象并把它设为忙
            if (!pObj.isBusy()) {
                obj = pObj.getObject();
                pObj.setBusy(true);
            }
        }        return obj;// 返回找到到的可用对象
    }    /**
     * 此函数返回一个对象到对象池中,并把此对象置为空闲。 所有使用对象池获得的对象均应在不使用此对象时返回它。
     */

    public void returnObject(T obj) {        // 确保对象池存在,如果对象没有创建(不存在),直接返回
        if (objects == null) {            return;
        }
        PooledObject<T> pObj = null;
        Enumeration<PooledObject<T>> enumerate = objects.elements();        // 遍历对象池中的所有对象,找到这个要返回的对象对象
        while (enumerate.hasMoreElements()) {
            pObj = (PooledObject<T>) enumerate.nextElement();            // 先找到对象池中的要返回的对象对象
            if (obj == pObj.getObject()) {                // 找到了 , 设置此对象为空闲状态
                pObj.setBusy(false);                break;
            }
        }
    }    /**
     * 关闭对象池中所有的对象,并清空对象池。
     */
    public synchronized void closeObjectPool() {        // 确保对象池存在,如果不存在,返回
        if (objects == null) {            return;
        }
        PooledObject<T> pObj = null;
        Enumeration<PooledObject<T>> enumerate = objects.elements();        while (enumerate.hasMoreElements()) {
            pObj = (PooledObject<T>) enumerate.nextElement();            // 如果忙,等 0.5 秒
            if (pObj.isBusy()) {
                wait(500); // 等
            }            // 从对象池向量中删除它
            objects.removeElement(pObj);
        }        // 置对象池为空
        objects = null;
    }    /**
     * 使程序等待给定的毫秒数
     */
    private void wait(int mSeconds) {        try {
            Thread.sleep(mSeconds);
        } catch (InterruptedException e) {
        }
    }
}

为了泛化处理,这个对象池是个抽象类,接下来具体实现一个

代码语言:javascript
复制
public class DefaultObjectPool extends ObjectPool<String> {    @Override
    public PooledObject<String> create(){        return new PooledObject<String>(new String(""+1));
    }

}

最后测试下:

代码语言:javascript
复制
    public static void main(String[] args) {
        ObjectPool<String> objPool = new DefaultObjectPool();
        objPool.createPool();
        String obj = objPool.getObject();
        objPool.returnObject(obj);
        objPool.closeObjectPool();
    }

4、开源的对象池

上面的例子基本够用,但是commons-pool提供了一套很好用的对象池组件,使用也很简单。 org.apache.commons.pool.ObjectPool定义了一个简单的池化接口,有三个对应实现,与我们的 Vector 这个集合不同的是,commons-pool提供了多样的集合,包括先进先出(FIFO),后进先出(LIFO)

StackObjectPool :实现了后进先出(LIFO)行为。 SoftReferenceObjectPool: 实现了后进先出(LIFO)行为。另外,对象池还在SoftReference 中保存了每个对象引用,允许垃圾收集器针对内存需要回收对象。

KeyedObjectPool定义了一个以任意的key访问对象的接口(可以池化对种对象),有两种对应实现。 GenericKeyedObjectPool :实现了先进先出(FIFO)行为。 StackKeyedObjectPool : 实现了后进先出(LIFO)行为。

PoolableObjectFactory 定义了池化对象的生命周期方法,我们可以使用它分离被池化的不同对象和管理对象的创建,持久,销毁。 BasePoolableObjectFactory这个实现PoolableObjectFactory接口的一个抽象类,我们可用扩展它实现自己的池化工厂。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-12-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 技术与生活 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2、对象池
  • 3、自定义一个低质量的对象池
  • 4、开源的对象池
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档