Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there any good tutorials or examples on how to use Java ObjectPool/pools?

I am trying to create a pool of channels/connections to a queue server and was trying to use ObjectPool but am having trouble using it from the example on their site.

So far I have threads that do work but I want each of them to grab a channel from the pool and then return it. I understand how to use it(borrowObject/returnObjects) but not sure how to create the intial pool.

Here's how channels are made in rabbitmq:

ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();

and my code just uses channel to do stuff. I'm confused because the only example I could find (on their site) starts it like this:

private ObjectPool<StringBuffer> pool;

    public ReaderUtil(ObjectPool<StringBuffer> pool) { 
        this.pool = pool;
    }

Which does not make sense to me. I realized this is common to establishing database connections so I tried to find tutorials using databases and ObjectPool but they seem to use DBCP which is specific to databases(and I can't seem to use the logic for my queue server).

Any suggestions on how to use it? Or is there a another approach used for pools in java?

like image 497
Lostsoul Avatar asked Apr 28 '12 23:04

Lostsoul


2 Answers

They create a class that creates objects & knows what to do when they are returned. That might be something like this for you:

public class PoolConnectionFactory extends BasePoolableObjectFactory<Connection> { 

    private final ConnectionFactory factory;
    public PoolConnectionFactory() {
        factory = new ConnectionFactory();
        factory.setHost("localhost");
    }

    // for makeObject we'll simply return a new Connection
    public Connection makeObject() { 
        return factory.newConnection();
    } 

    // when an object is returned to the pool,  
    // we'll clear it out 
    public void passivateObject(Connection con) { 
        con.I_don't_know_what_to_do(); 
    } 

    // for all other methods, the no-op  
    // implementation in BasePoolableObjectFactory 
    // will suffice 
}

now you create a ObjectPool<Connection> somewhere:

ObjectPool<Connection> pool = new StackObjectPool<Connection>(new PoolConnectionFactory());

then you can use pool inside your threads like

Connection c = pool.borrowObject();
c.doSomethingWithMe();
pool.returnObject(c);

The lines that don't make sense to you are a way to pass the pool object to a different class. See last line, they create the pool while creating the reader.

new ReaderUtil(new StackObjectPool<StringBuffer>(new StringBufferFactory()))
like image 200
zapl Avatar answered Oct 03 '22 03:10

zapl


You'll need a custom implementation of PoolableObjectFactory to create, validate, and destroy the objects you want to pool. Then pass an instance of your factory to an ObjectPool's contructor and you're ready to start borrowing objects.

Here's some sample code. You can also look at the source code for commons-dbcp, which uses commons-pool.

import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;

public class PoolExample {
    public static class MyPooledObject {
        public MyPooledObject() {
            System.out.println("hello world");
        }

        public void sing() {
            System.out.println("mary had a little lamb");
        }

        public void destroy() {
            System.out.println("goodbye cruel world");
        }
    }

    public static class MyPoolableObjectFactory extends BasePoolableObjectFactory<MyPooledObject> {
        @Override
        public MyPooledObject makeObject() throws Exception {
            return new MyPooledObject();
        }

        @Override
        public void destroyObject(MyPooledObject obj) throws Exception {
            obj.destroy();
        }
        // PoolableObjectFactory has other methods you can override
        // to valdiate, activate, and passivate objects.
    }

    public static void main(String[] args) throws Exception {
        PoolableObjectFactory<MyPooledObject> factory = new MyPoolableObjectFactory();
        ObjectPool<MyPooledObject> pool = new GenericObjectPool<MyPooledObject>(factory);

        // Other ObjectPool implementations with special behaviors are available;
        // see the JavaDoc for details

        try {
            for (int i = 0; i < 2; i++) {
                MyPooledObject obj;

                try {
                    obj = pool.borrowObject();
                } catch (Exception e) {
                    // failed to borrow object; you get to decide how to handle this
                    throw e;
                }

                try {
                    // use the pooled object
                    obj.sing();

                } catch (Exception e) {
                    // this object has failed us -- never use it again!
                    pool.invalidateObject(obj);
                    obj = null; // don't return it to the pool

                    // now handle the exception however you want

                } finally {
                    if (obj != null) {
                        pool.returnObject(obj);
                    }
                }
            }
        } finally {
            pool.close();
        }
    }
}
like image 28
dnault Avatar answered Oct 03 '22 02:10

dnault