Skip to content

Instantly share code, notes, and snippets.

@czyrux
Last active August 29, 2015 14:05
Show Gist options
  • Save czyrux/818c1331586194878d10 to your computer and use it in GitHub Desktop.
Save czyrux/818c1331586194878d10 to your computer and use it in GitHub Desktop.
Tiny helper class for creating pools of objects in Java. Specially suitable for Android Projects
/**
* Helper class for creating pools of objects.
*
* An example use looks like this:
*
* <pre>
* public class MyPooledClass implements {@link PoolObject}{
*
* private static final SynchronizedPool<MyPooledClass> sPool = new SynchronizedPool<MyPooledClass>(new MyPooledFactoryClass(), 10);
*
* public static MyPooledClass obtain() {
* return sPool.acquire();
* }
*
* public void recycle() {
* sPool.release(this);
* }
*
* public void reset() {
* // reset variables
* }
* . . .
*
* static class MyPooledFactoryClass implements Pools.PoolObjectFactory<MyPooledClass>
* {
* public MyPooledClass createPoolObject() {
* return new MyPooledClass();
* }
* }
* }
* </pre>
*
* @hide
*/
public final class Pools {
private Pools() {
}
/**
* Poolable Object. It solves the problem of using a object with a obsolete
* state.
*/
public interface PoolObject {
/**
* Reset object to default state
*/
public void reset();
}
/**
* Create objects for the object pool. It allows the Pool to never return a
* null object, even when object are not available on the Pool
*
* @param <T>
* The pooled type.
*/
public interface PoolObjectFactory<T extends PoolObject> {
/**
* Creates a new object for the object pool.
*
* @return new object instance for the object pool
*/
public T createPoolObject();
}
/**
* Interface for managing a pool of objects.
*
* @param <T>
* The pooled type.
*/
public interface Pool<T extends PoolObject> {
/**
* @return An instance from the pool if such is available.
*/
public T acquire();
/**
* Release an instance to the pool.
*
* @param instance
* The instance to release.
* @return Whether the instance was put in the pool.
* @throws IllegalStateException
* If the instance is already in the pool.
*/
public boolean release(T instance);
}
/**
* Simple (non-synchronized) pool of objects.
*
* @param <T>
* The pooled type.
*/
public static class SimplePool<T extends PoolObject> implements Pool<T> {
private final PoolObjectFactory<T> poolFactory;
private final PoolObject[] pool;
private int lastPooledIndex;
/**
* Creates a new instance.
*
* @param maxPoolSize
* The max pool size.
* @throws IllegalArgumentException
* If the max pool size is less than zero.
*/
public SimplePool(int maxPoolSize) {
if (maxPoolSize <= 0)
throw new IllegalArgumentException(
"The max pool size must be > 0");
lastPooledIndex = -1;
poolFactory = null;
pool = new PoolObject[maxPoolSize];
}
/**
* Creates a new instance. If the factory is not null the Pool will
* never return a null object when {@link SimplePool#acquire()} is call,
* even if there are not objects available on the Pool
*
* @param factory
* the object pool factory instance.
* @param maxPoolSize
* The max pool size.
* @throws IllegalArgumentException
* If the max pool size is less than zero.
*/
public SimplePool(PoolObjectFactory<T> factory, int maxPoolSize) {
if (maxPoolSize <= 0)
throw new IllegalArgumentException(
"The max pool size must be > 0");
lastPooledIndex = -1;
poolFactory = factory;
pool = new PoolObject[maxPoolSize];
}
@Override
@SuppressWarnings("unchecked")
public T acquire() {
T instance = null;
if (lastPooledIndex == -1) {
if (poolFactory != null) {
instance = (T) poolFactory.createPoolObject();
}
} else {
instance = (T) pool[lastPooledIndex];
instance.reset();
pool[lastPooledIndex] = null;
lastPooledIndex--;
}
return instance;
}
@Override
public boolean release(T instance) {
if (isInPool(instance)) {
throw new IllegalStateException("Already in the pool!");
}
if (lastPooledIndex < pool.length - 1) {
lastPooledIndex++;
pool[lastPooledIndex] = instance;
return true;
}
return false;
}
private boolean isInPool(T instance) {
for (int i = 0; i < lastPooledIndex; i++) {
if (pool[i] == instance) {
return true;
}
}
return false;
}
}
/**
* Synchronized pool of objects.
*
* @param <T>
* The pooled type.
*/
public static class SynchronizedPool<T extends PoolObject> extends
SimplePool<T> {
private final Object lockObject = new Object();
/**
* Creates a new instance.
*
* @param maxPoolSize
* The max pool size.
* @throws IllegalArgumentException
* If the max pool size is less than zero.
*/
public SynchronizedPool(int maxPoolSize) {
super(maxPoolSize);
}
/**
* Creates a new instance. If the factory is not null the Pool will
* never return a null object when {@link SimplePool#acquire()} is call,
* even if there are not objects available on the Pool
*
* @param factory
* the object pool factory instance.
* @param maxPoolSize
* The max pool size.
* @throws IllegalArgumentException
* If the max pool size is less than zero.
*/
public SynchronizedPool(PoolObjectFactory<T> factory, int maxPoolSize) {
super(factory, maxPoolSize);
}
@Override
public T acquire() {
synchronized (lockObject) {
return super.acquire();
}
}
@Override
public boolean release(T element) {
synchronized (lockObject) {
return super.release(element);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment