java对象池化

来源:互联网 发布:淘宝店铺资质代表什么 编辑:程序博客网 时间:2024/05/26 20:23
对象池化技术 
 对象池化的基本思路是:将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用,从而在一定程度上减少频繁创建对象所造成的开销。用于充当保存对象的“容器”的对象,被称为“对象池”(Object Pool,或简称Pool)。


 对于没有状态的对象(例如String),在重复使用之前,无需进行任何处理;对于有状态的对象(例如StringBuffer),在重复使用之前,就需要把它们恢复到等同于刚刚生成时的状态。由于条件的限制,恢复某个对象的状态的操作不可能实现了的话,就得把这个对象抛弃,改用新创建的实例了。


 并非所有对象都适合拿来池化——因为维护对象池也要造成一定开销。对生成时开销不大的对象进行池化,反而可能会出现“维护对象池的开销”大于“生成新对象的开销”,从而使性能降低的情况。但是对于生成时开销可观的对象,池化技术就是提高性能的有效策略了。




什么时候不要池化 
  采用对象池化的本意,是要通过减少对象生成的次数,减少花在对象初始化上面的开销,从而提高整体的性能。然而池化处理本身也要付出代价,因此,并非任何情况下都适合采用对象池化。




 对于类似Point这样的轻量级对象,进行池化处理后,性能反而下降,因此不宜池化;  


  对于类似Hashtable这样的中量级对象,进行池化处理后,性能基本不变,一般不必池化(池化会使代码变复杂,增大维护的难度);


   对于类似JPanel这样的重量级对象,进行池化处理后,性能有所上升,可以考虑池化。


   根据使用方法的不同,实际的情况可能与这一测量结果略有出入。在配置较高的机器和技术较强的虚拟机上,不宜池化的对象的范围可能会更大。不过,对于像网络和数据库连接这类重量级的对象来说,目前还是有池化的必要。


  基本上,只在重复生成某种对象的操作成为影响性能的关键因素的时候,才适合进行对象池化。如果进行池化所能带来的性能提高并不重要的话,还是不采用对象池化技术,以保持代码的简明,而使用更好的硬件和更棒的虚拟机来提高性能为佳。



在Java中可以自定义或者借用第三方类库(如:apache commons-pool)实现对象池

以下是我自己实现的对象池,相当粗糙

思路是:

线程池中有两个集合,一个集合A存放空闲中的对象,一个集合B存放使用中的对象,

线程从A中拿到对象使用,并放入B中,当线程使用完对象之后从B中取出放回A中,

有状态的对象在使用之前先恢复为初始化状态,

当线程池中所有的对象都是使用中时(即都属于集合B),线程等待,当有线程返还对象时,线程唤醒。

001package common.pool;
002 
003import java.lang.reflect.Field;
004import java.util.Collections;
005import java.util.HashSet;
006import java.util.Iterator;
007import java.util.Set;
008 
009/**
010 *
011 * @author JiaZhiTang
012 *自定义对象池
013 */
014@SuppressWarnings({"unchecked","hiding"})
015public class DIYObjectPool<E> {
016    private  Set<Object> activeSet = Collections.synchronizedSet(newHashSet<Object>());//正在被使用的对象的集合,已被同步
017    private  Set<Object> idleSet = Collections.synchronizedSet(newHashSet<Object>());//空闲的对象的集合,已被同步
018     
019    private Integer maxObjetc = 100;//最大对象数,默认值100
020    private Class<E> cls;//对象池 的类,因为java不能 直接使用泛型创建对象   T t = new T();
021    private Object lock = new Object();//线程等待监视器
022 
023 
024    /**
025     * 构造方法
026     * @param maxObjetc
027     * @param cls
028     */
029    public DIYObjectPool(Integer maxObjetc, Class<E> cls) {
030        this.maxObjetc = maxObjetc;
031        this.cls = cls;
032    }
033 
034    /**
035     * 从线程池中取出对象
036     * @param <E>
037     * @return
038     * @throws Exception
039     */
040    public synchronized <E> E borrowObject() throws Exception{
041        Object obj = null;
042        if(idleSet.size()>0){
043            Iterator<Object> iterator = idleSet.iterator();
044            obj = iterator.next();
045        }
046        if(obj != null){
047            idleSet.remove(obj);
048            activeSet.add(obj);
049        }else{
050            int size = activeSet.size()+idleSet.size();
051            if(size>=maxObjetc){
052                synchronized (lock) {
053                    System.out.println("-----池中无对象,线程等待-----");
054                    lock.wait();
055                }
056                return borrowObject();
057            }else{
058                obj = cls.newInstance();
059                activeSet.add(obj);
060            }
061        }
062         
063        System.out.println("池中总对象数: "+(activeSet.size()+idleSet.size())+" ,使用中:"+activeSet.size()+" ,空闲中:"+idleSet.size());
064         
065        clearObject(obj);//有状态对象恢复默认初始化
066        return (E)obj;
067    }
068     
069    /**
070     * 对象使用完毕,返还线程池
071     * @param obj
072     */
073    public void returnObject(Object obj){
074        if(obj != null){
075            activeSet.remove(obj);
076            idleSet.add(obj);
077            synchronized (lock) {
078                System.out.println("唤醒等待线程");
079                lock.notify();
080//              lock.notifyAll();
081            }
082             
083        }
084    }
085 
086 
087    /**
088     * 有状态对象恢复默认初始化
089     * @param obj
090     */
091    public void clearObject(Object obj) throws Exception{
092        Class<?> cls = obj.getClass();
093        Field[] fields = cls.getDeclaredFields();
094        for (Field field : fields) {
095            field.setAccessible(true);
096            field.set(obj, null);
097        }
098    }
099 
100 
101    public static void main(String[] args) throws Exception {
102        //初始化线程池
103        int max = 1000;
104        DIYObjectPool<Object> pool = new DIYObjectPool<Object>(max,Object.class);
105         
106        //自定义运行线程
107        class TestThread extends Thread{
108            DIYObjectPool objectPool;
109 
110            public TestThread(DIYObjectPool objectPool) {
111                this.objectPool = objectPool;
112            }
113             
114            @Override
115            public void run() {
116                try {
117                    Object obj = objectPool.borrowObject();
118                    Thread.sleep(3000);//假设对象被一个线程使用的3秒钟
119                    objectPool.returnObject(obj);
120                catch (Exception e) {
121                    e.printStackTrace();
122                }
123            }
124        }
125         
126        //并发max*2个线程
127        max = max*2;
128        for (int i = 0; i < max; i++) {
129            new TestThread(pool).start();
130        }
131    }
132     
133}


不过实际开发中还是借用第三方类库来得好,毕竟自己水平有限     (╯﹏╰)

工厂类

01package common.pool;
02 
03import org.apache.commons.pool.PoolableObjectFactory;
04 
05@SuppressWarnings({"unchecked"})
06public class ObjectPoolFactory implements PoolableObjectFactory {
07 
08    private Class cls;
09    private static final String INIT_METHOD = "clearObject";//有状态对象恢复初始化的方法
10     
11     
12    public ObjectPoolFactory(Class cls) {
13        this.cls = cls;
14    }
15 
16    public void activateObject(Object arg0) throws Exception {
17        System.out.println("有状态对象恢复初始化");
18        try {
19            cls.getDeclaredMethod(INIT_METHOD).invoke(arg0);//有状态对象恢复初始化
20        catch (Exception e) {
21        }
22    }
23 
24    public void destroyObject(Object arg0) throws Exception {
25         
26    }
27 
28    public Object makeObject() throws Exception {
29        System.out.println("创建新对象");
30        return cls.newInstance();//创建新对象
31    }
32 
33    public void passivateObject(Object arg0) throws Exception {
34         
35    }
36 
37    public boolean validateObject(Object arg0) {
38        return false;
39    }
40 
41}

对象池

01package common.pool;
02 
03import org.apache.commons.pool.impl.GenericObjectPool;
04 
05 
06@SuppressWarnings({"unchecked"})
07public class ObjectPool {
08     
09    private GenericObjectPool pool;
10     
11    public ObjectPool(Class cls) {
12        this.pool = new GenericObjectPool(new ObjectPoolFactory(cls));
13        pool.setMaxActive(2);//最大活动对象
14        pool.setMaxIdle(1);//最大空闲对象
15        pool.setMaxWait(100000);//最大等待时间
16    }
17     
18    /**
19     * 池中取出对象
20     * @param <T>
21     * @return
22     */
23    public <T> T borrowObject(){
24        T obj = null;
25        try {
26            obj = (T)pool.borrowObject();
27            System.out.println("获得对象");
28        catch (Exception e) {
29            System.out.println(e);
30        }
31        return obj;
32    }
33     
34    /**
35     * 对象放回池中
36     * @param obj
37     */
38    public void returnObject(Object obj){
39        try {
40            pool.returnObject(obj);
41            System.out.println("返还对象");
42        catch (Exception e) {
43            System.out.println(e);
44        }
45    }
46     
47}

测试

view source
print?
01package common.pool;
02 
03public class Test {
04     
05    public static ObjectPool pool = new ObjectPool(Object.class);
06 
07    public static void main(String[] args) {
08        for (int i = 0; i < 2000; i++) {
09            new Thread(){
10                public void run() {
11                    Object obj = Test.pool.borrowObject();
12                    System.out.println(obj.toString());
13                    try {
14                        Thread.sleep(1000);
15                    catch (Exception e) {
16                    }
17                    Test.pool.returnObject(obj);
18                };
19            }.start();
20        }
21    }
22 
23}

这里依赖于  commons-pool-1.5.6.jar

原创粉丝点击