Sunday, September 22, 2013

Java Object Pool Implementations and Comparison


I was looking for a Java solution for Object Pool implementation. Focus on high throughput and low latency, especially under multiple thread i.e. high concurrency environment. 

Below are possible solutions that I am looking at:
I have tested multiple implementations under high concurrency. Here is the comparison chart.





Implementation with Java ConcurrentLinkedQueue:
    
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 
 * Implementation with Java ConcurrentLinkedQueue
 * 
 * @author stones333 
 *
 */
final public class PoolWithConcurrentLinkedQueue<T> implements ObjectPoolInterface<T> {
	
	public static interface ObjectPoolFactory<T>
	{
		public T create();
	}

	final private Queue<T> objects;
    private ObjectPoolFactory<T> factory=null;

    public PoolWithConcurrentLinkedQueue(ObjectPoolFactory<T> objFactory) {
    	this.factory = objFactory;
        this.objects = new ConcurrentLinkedQueue<T>();
    }

    public PoolWithConcurrentLinkedQueue(ObjectPoolFactory<T> objFactory, long count) {
    	this.factory = objFactory;
        this.objects = new ConcurrentLinkedQueue<T>();
        for (long i=0; i<count; i++) {
        	objects.add( factory.create() );
        }
    }

    public T addObject() {
        T t = factory.create();
        objects.add(t);
        return t;
    }

    public T borrowObject() {
        T t;
        if ((t = objects.poll()) == null) {
            t = factory.create();
            objects.add(t);
        }
        return t;
    }

    public void returnObject(T object) {
        this.objects.offer(object);   
    }
    
    public int size() { return objects.size(); };
}






Implementation with Java LinkedBlockingQueue :
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;



/**
 * 
 * Implementation with Java LinkedBlockingQueue
 * 
 * @author stones333 
 *
 */
public class PoolWithLinkedBlockingQueue<T> implements ObjectPoolInterface<T> {
	
	public static interface ObjectPoolFactory<T>
	{
		public T create();
	}


	final private LinkedBlockingQueue<T> objects;
    private ObjectPoolFactory<T> factory=null;

    
    
    public PoolWithLinkedBlockingQueue(ObjectPoolFactory<T> objFactory) {
    	this.factory = objFactory;
        this.objects = new LinkedBlockingQueue<T>();
    }

    public PoolWithLinkedBlockingQueue(ObjectPoolFactory<T> objFactory, long count) {
    	this.factory = objFactory;
        this.objects = new LinkedBlockingQueue<T>();
        for (long i=0; i<count; i++) {
        	objects.add( factory.create() );
        }
    }


    public T addObject() {
        T t = factory.create();
        objects.add(t);
        return t;
    }

    public T borrowObject() {
        T t;
        if ((t = objects.poll()) == null) {
            t = factory.create();
            objects.add(t);
        }
        return t;
    }

    //
    public void returnObject(T object) {
        this.objects.offer(object);   
    }
    
    
    public int size() { return objects.size(); };
}






Implementation with Java BlockingQue: 
import java.util.Collection;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;



/**
 * 
 * Implementation with Java BlockingQueue
 * 
 * @author stones333 
 *
 */
public final class PoolWithBlockingQue <T> implements ObjectPoolInterface<T> {
	
	public static interface ObjectPoolFactory<T>
	{
		public T create();
	}

    private final BlockingQueue<T> objects;
    private ObjectPoolFactory<T> factory = null;
    
    public PoolWithBlockingQue(ObjectPoolFactory<T> objFactory) {
    	this.factory = objFactory;
        this.objects = new LinkedBlockingQueue<T>();
    }

    public PoolWithBlockingQue(ObjectPoolFactory<T> objFactory, long count) {
    	this.factory = objFactory;
        this.objects = new LinkedBlockingQueue<T>();
        for (long i=0; i<count; i++) {
        	objects.add( factory.create() );
        }
    }

    public PoolWithBlockingQue(ObjectPoolFactory<T> objFactory,  Collection<? extends T> objects) {
    	this.factory = objFactory;
        this.objects = new ArrayBlockingQueue<T>(objects.size(), false, objects);
    }


    public PoolWithBlockingQue(Collection<? extends T> objects) {
    	this(null,  objects);
    }

    public T borrowObject() throws InterruptedException {
        T t = this.objects.take();
        if (t==null) {
        	t = (factory!=null) ? factory.create() : null;
        	if (t!=null) objects.add(t);
        }
        return t;
    }

    public void returnObject(T object) throws InterruptedException {
        this.objects.put(object);
    }
}





Java Test Code:

/**
 * 
 * MultiThread Test code for Object Pool implementations  
 * 
 * @author stones333 
 *
 */

public class ObjectPoolTest {
	
	private ObjectPoolInterface<StringBuffer> objectPool = null;
	
	
	public ObjectPoolInterface<StringBuffer> getObjectPool() {
		return objectPool;
	}


	public void setObjectPool(ObjectPoolInterface<StringBuffer> objectPool) {
		this.objectPool = objectPool;
	}


	public Object fetchObject() throws RuntimeException, InterruptedException {
		StringBuffer obj = objectPool.borrowObject();
		objectPool.returnObject(obj);
		return obj;
	}

	
	public Object fetchObjects() throws RuntimeException, InterruptedException {
		
		Object obj = null;
		for (int i=0; i<10000; i++) {
			obj = fetchObject();
			if (obj==null) {
				throw new RuntimeException ("object from pool is null");
			}
		}
		return obj;
	}



}


MultiThread Test code for Object Pool implementation with LinkedBlockingQueue:
/**
 * 
 * MultiThread Test code for Object Pool implementation with LinkedBlockingQueue  
 * 
 * @author stones333 
 *
 */

public class PoolWithLinkedBlockingQueueTest extends ObjectPoolTest {

	public static class TestPoolFactory<T> implements PoolWithLinkedBlockingQueue.ObjectPoolFactory<T>  {

		@Override
		public T create() {
			StringBuffer obj = new StringBuffer();
			return (T) obj;
		}
	}
	
	static private ObjectPoolInterface<StringBuffer> objects = new PoolWithLinkedBlockingQueue<StringBuffer>( new TestPoolFactory<StringBuffer>(), 1000000);
	
	public PoolWithLinkedBlockingQueueTest () {
		super.setObjectPool(objects);
	}


}

Test code for other Java Object Pool implementations are obvious and omitted here.

No comments:

Post a Comment