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 }