1 /* 2 * Copyright (c) 2003-2008 by Cosylab d. d. 3 * 4 * This file is part of Java-Common. 5 * 6 * Java-Common is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * Java-Common is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with Java-Common. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package com.cosylab.util; 21 22 /** 23 * A simple object pool. This pool is created with an initial capacity and a class 24 * (must be a subclass of <code>PoolableObject</code>) of the objects it contains. 25 * The pool contains at most <code>capacity</code> of resurrected objects, which it 26 * clears (by invoking <code>PoolableObject.clear</code>) before returning them to the 27 * user. The user can request a new instance. If found in the pool, it is cleared and 28 * returned. Otherwise a new instance creation is attempted with the default constructor. 29 * If it fails, <code>null</code> is returned. 30 */ 31 32 public class ObjectPool 33 { 34 private ObjectFactory objectFactory = null; 35 private PoolableObject[] freeObjects = null; 36 private int ix = -1; 37 /** 38 * Creates a new object pool with an initial capacity and the type of the pooled objects. 39 * ObjectPool will try to use DefaultObjecFactory with the type of the pooled objects. 40 * 41 * @param objectType a type descending from <code>PoolableObject</code> 42 * @param capacity the initial capacity of the object pool 43 */ 44 public ObjectPool(Class objectType, int capacity) 45 { 46 this(new DefaultObjectFactory(objectType),capacity); 47 } 48 /** 49 * Creates a new object pool with an initial capacity and ObjectFactory for creating new instances of pooled objects. 50 * 51 * @param objectFactory ObjectFactory for creating new instances of pooled objects 52 * @param capacity the initial capacity of the object pool 53 */ 54 public ObjectPool(ObjectFactory objectFactory,int capacity) 55 { 56 if (objectFactory == null) throw new NullPointerException("objectFactory"); 57 if (capacity < 1) throw new IllegalArgumentException("Capacity cannot be less then 1."); 58 this.objectFactory = objectFactory; 59 freeObjects = new PoolableObject[capacity]; 60 } 61 62 /** 63 * Produces a new instance. Returns an object from the pool, if it is available. 64 * Otherwise tries to create new instance with <code>ObjectFactory</code> 65 * 66 * @return PoolableObject a new cleared object ready for use or <code>null</code> 67 * if the new type construction failed 68 */ 69 public synchronized PoolableObject newInstance() 70 { 71 PoolableObject o=null; 72 if (ix < 0) 73 { 74 // instantiated++; 75 // checkCacheSize(); 76 o=objectFactory.newInstance(); 77 if (o==null) return null; 78 } 79 else 80 { 81 // cached++; 82 // checkCacheSize(); 83 o = freeObjects[ix]; 84 ix--; 85 } 86 o.setObjectPool(this); 87 return o; 88 } 89 90 /** 91 * Must be invoked from the <code>finalize</code> method of the 92 * <code>PoolableObject</code>s to return them to the object pool. 93 * This method will add the object to the pool if there is any room 94 * left, otherwise the reference and the object will be discarded. 95 * 96 * @param p the object being returned to the pool 97 */ 98 public synchronized void returnToPool(PoolableObject p) 99 { 100 if (p == null) throw new NullPointerException("p"); 101 if (ix >= freeObjects.length - 1) return; 102 ix++; 103 freeObjects[ix] = p; 104 p.clear(); 105 } 106 107 /** 108 * Contains a test sample implementation of a poolable object and the use 109 * of thread pool. 110 * 111 * @param args ignored. 112 */ 113 public static void main(String[] args) 114 { 115 class TestObj implements PoolableObject 116 { 117 private int value = 1; 118 private double v1 = 5; 119 private String t = null; 120 121 private ObjectPool pool = null; 122 123 public TestObj() 124 { 125 } 126 127 public void finalize() 128 { 129 if (pool != null) pool.returnToPool(this); 130 } 131 public void clear() 132 { 133 value = 1; 134 } 135 public void setValue(int value) 136 { 137 this.value = value; 138 t = String.valueOf(value); 139 v1 = value; 140 } 141 142 public PoolableObject createInstance(){ 143 return new TestObj(); 144 } 145 146 public void setObjectPool(ObjectPool pool) 147 { 148 this.pool = pool; 149 } 150 151 } 152 class TestFactory implements ObjectFactory{ 153 154 /* (non-Javadoc) 155 * @see com.cosylab.util.ObjectFactory#newInstance() 156 */ 157 public PoolableObject newInstance() { 158 return new TestObj(); 159 } 160 } 161 162 ObjectPool pool = new ObjectPool(new TestFactory(), 10000); 163 try 164 { 165 Thread.sleep(1000); 166 } catch (InterruptedException ie) 167 { 168 } 169 long time1 = System.currentTimeMillis(); 170 for (int i = 1; i < 1000000; i++) 171 { 172 TestObj obj = (TestObj)pool.newInstance();/*null;*/ 173 if (obj == null) 174 { 175 obj = new TestObj(); 176 obj.setObjectPool(pool); 177 } 178 obj.setValue(i); 179 } 180 System.out.println("Total time: " + (System.currentTimeMillis() - time1)); 181 } 182 }