View Javadoc

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 }