常用优化组件——对象复用—"池"

对象池化,是目前非常常用的一种系统优化技术。它的核心思想是:如果一个类被频繁请求使用,那么不必每次都生成一个实例,可以将这个类的一些实例保存在一个"池"中,待需要使用的时候直接从池中获取。这个"池"就称为对象池

在实现细节上,它可能是一个数组,一个链表或者任何集合类

对象池的使用非常广泛,其中最熟悉的,就是线程池数据库连接池

线程池

线程池中保存着可以被重用的线程对象,当有任务被提交到线程池中,系统并不需要新建线程,而是从线程池中获取一个可用的线程执行这个任务。在任务结束后,也不关闭线程,而是将它返回到线程池中,以便下次继续使用。

由于线程的创建和销毁是较为费时的工作,因此在线程调度频繁的系统中,线程池可以很好地改善性能

数据库连接池

数据库连接池是一种特殊的对象池,它用于维护数据库连接的集合。当系统需要访问数据库时,不需要重新建立数据库连接,而可以直接从池中取出;在数据库操作完成后,也不关闭数据库连接,而是将连接返回到连接池中。

由于数据库连接的创建和销毁是重量级的操作,因此避免频繁进行这两个操作,对改善系统的性能有积极的意义

Druid连接池配置

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="initialSize" value="${jdbc.initialSize}"/>
</bean>


dataSources.properties文件
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicde=true&characterEncoding=utf-8
jdbc.username=root	
jdbc.password=
jdbc.initialSize=5

扩展

除了线程池和数据库连接池,对于普通的Java对象,在必要时可也以进行池化管理。对于那些经常使用,并且创建很费时的大型对象来说,使用对象池维护,不仅可以节省获得对象实例的成本,还可以减轻GC频繁回收这些对象产生的系统压力但是对于生成对象开销很小的对象进行池化,反而可能得不偿失,维护对象池的成本可能会大于对象池带来的好处

在实际开发中,Apache已经提供了一个Jakarta Commons Pool对象池组件,可以直接使用

// Jakarta Commons Pool定义的对象池接口
public interface ObjectPool {
    Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException;
    void returnObject(Object var1) throws Exception;
    void invalidateObject(Object var1) throws Exception;
    void addObject() throws Exception, IllegalStateException, UnsupportedOperationException;
    int getNumIdle() throws UnsupportedOperationException;
    int getNumActive() throws UnsupportedOperationException;
    void clear() throws Exception, UnsupportedOperationException;
    void close() throws Exception;
    void setFactory(PoolableObjectFactory var1) throws IllegalStateException, UnsupportedOperationException;
}
// 另一个重要接口,告诉对象池如何创建一个对象,如何销毁一个对象
public interface PoolableObjectFactory {
    Object makeObject() throws Exception;				// 定义如何创建一个新的对象实例
    void activateObject(Object var1) throws Exception;	// 在对象从对象池取出钱,会激活这对象
    void passivateObject(Object var1) throws Exception;	// 在对象返回对象池时被调用
    void destroyObject(Object var1) throws Exception;	// 对象从对象池中被销毁时,会执行这个方法
    boolean validateObject(Object var1);				// 判断对象是否可用
}

下面这段代码显示了一个简单的对象池工厂

public class PoolableObjectFactoryDemo implements PoolableObjectFactory {
    private static AtomicInteger counter = new AtomicInteger(0);

    @Override
    public Object makeObject() throws Exception {       // 创建对象
        Object obj = String.valueOf(counter.getAndIncrement());
        System.out.println("Create Object:" + obj);
        return obj;
    }

    @Override
    public void activateObject(Object obj) throws Exception {   // 在被取出前调用
        System.out.println("Before borrow:" + obj);
    }

    @Override
    public void passivateObject(Object obj) throws Exception {  // 当对象返回池中时被调用
        System.out.println("return:" + obj);
    }

    @Override
    public boolean validateObject(Object obj) {
        return true;
    }

    @Override
    public void destroyObject(Object obj) throws Exception {    // 对象被销毁时调用
        System.out.println("Destroying Object:" + obj);
    }
}
public class ObjectPoolDemo {
    static PoolableObjectFactory factory = new PoolableObjectFactoryDemo();
    static ObjectPool pool = new GenericObjectPool(factory);
    private static AtomicInteger endcount = new AtomicInteger(0);
    public static class PoolThread extends Thread {
        @Override
        public void run() {
            Object obj = null;
            try {
                for (int i = 0; i < 10; i++) {
                    System.out.println("== " + i + " ==");
                    obj = pool.borrowObject();
                    System.out.println(obj + " is get");
                    pool.returnObject(obj);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                endcount.getAndIncrement();
            }
        }
    }

    public static void main(String[] args) {
        new PoolThread().start();
        new PoolThread().start();
        new PoolThread().start();
        try {
            while (true) {
                if (endcount.get() == 3) {  // 等待三个线程全部结束
                    pool.close();
                    break;
                }
            }
        } catch (Exception e) {

        }
    }
}
// 运行结果
== 0 ==
== 0 ==
== 0 ==
Create Object:1
Create Object:0
Create Object:2
Before borrow:1
1 is get
return:1
== 1 ==
Before borrow:1
1 is get
return:1
== 2 ==
Before borrow:1
1 is get
return:1
== 3 ==
Before borrow:1
1 is get
return:1
== 4 ==
Before borrow:1
1 is get
return:1
== 5 ==
Before borrow:1
1 is get
return:1
Before borrow:2
Before borrow:0
0 is get
return:0
== 1 ==
Before borrow:0
0 is get
return:0
== 2 ==
Before borrow:0
0 is get
return:0
== 3 ==
Before borrow:0
0 is get
return:0
== 4 ==
Before borrow:0
0 is get
return:0
== 5 ==
Before borrow:0
0 is get
return:0
2 is get
return:2
== 1 ==
Before borrow:2
2 is get
return:2
== 2 ==
Before borrow:2
2 is get
return:2
== 3 ==
Before borrow:2
2 is get
return:2
== 4 ==
Before borrow:2
2 is get
return:2
== 5 ==
Before borrow:2
2 is get
return:2
Destroying Object:2
Destroying Object:0
Destroying Object:1

可以看到,在3个线程向对象池获取对象的过程中,一共建立了3个对象。这3个对象不停地复用,当对象池被关闭时,使用了对象池工厂的destroyObject()方法,销毁对象,释放资源

注:只有重量级对象使用对象池技术才能提高系统性能,对轻量级的对象使用对象池,可能反而会降低系统性能

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值