Akshay Hiremath
Akshay Hiremath

Reputation: 1105

How to take and handle object from multiple threads in Java? How to create Multiple instances of Future

I need to create bunch of JMX connections to different hosts. I'm trying to create these connections in parallel. In this performance is much better now.

I've method to which I'm passing Collection of "host and port" entries. For each entry one connection will be created.

Now I'm submitting this task of creating connections to Multiple threads. But I don't know how to take return and store the connection objects created by threads.

code goes like this,

ConnectionFactory.createConnections(collection of hostportEntries)

class ConnectionFactory{

public static CollectionOfConnections createConnections(ListOfHostPorts)
{

   ExecutorService exec = Executors.newFixedThreadPool(4);

   for(iterate over hostportEntries)
   {
     Future<Connection> future1 = exec.submit(new connCreator(HostPortEntry));

      //Now here, connCreator is implementing Callable Interface and creating connection. and returning it. I'm taking reference of that Returned connection. 
//But how will I take              Multiple Connection objects returned by Multiple threads. I tried to create Future[] but OPTION like that doesn't seem to be there
      // Can anybody help here?????

   }

//if I succeed in getting the objects return then I'll store in one more collection and return those for further use of those connections.

}

Upvotes: 1

Views: 475

Answers (4)

mightyrick
mightyrick

Reputation: 910

Once each thread (your ConnectionCreator) creates a connection, it needs to register the handle to the newly created connection with a singleton of some sort. If you are running within an EJB container, this is easily accomplished with a session bean. Essentially, this session bean could become the "connection pool". Within the connection creator, you could do the following (For brevity, I am excluding exception handling and other things you should already be doing):

Inside of ConnectionCreator
============================

// Create your connection
Connection myConnection = doWhateverToCreateConnection();

// Presuming things went fine, get a handle to the session bean.  You could
// also potentially do this through resource injection using Spring or what not.  
Context ctx = new InitialContext();
ConnectionPoolBean connectionPoolBean = ( ConnectionPoolBean )ctx.lookup( "java:module/ConnectionPoolBean" );

// Now, register the connection with the pool
connectionPoolBean.registerConnection( myConnection );

Then in your ConnectionPoolBean, you hold a collection of connection objects. You should have register and unregister methods in those objects -- as well as possible getConnection... et cetera. Hope that helps.

Upvotes: 1

Caesar Ralf
Caesar Ralf

Reputation: 2233

You can use ExecutorCompletionService to run your connection openers and get them in order of the one who opens connection first :)

So, with your code, it would be something like

ExecutorService exec = Executors.newFixedThreadPool(4);
CompletionService<Result> ecs
       = new ExecutorCompletionService<Result>(exec);

for (HostPortEntry hpe : hostportEntries) { ecs.submit(new ConnCreator(hpe)); }

Collection<Connection> connections = new ArrayList<Connection>(hostportEntries.size());
for (int i = 0; i < hostportEntries.size(); i++) {
    // will add the created connections in order of what finish first.
    connections.add(ecs.take().get());
}
return connections;

Hope this helps :)

EDIT

IMPORTANT: you could not use CompletionService and Executor#submit. The thing is that your call to Future#get() must be done in another loop, or you will block your thread until the just submitted callable has finish. So:

Collection<Future> connCreatorsFuture = new ArrayList<Future<Connection>>(hostportEntries.size());
for (HostPortEntry hpe : hostportEntries) { connCreatorsFuture.add(exec.submit(new ConnCreator(hpe))); }

Collection<Connection> connections = new ArrayList<Connection>(hostportEntries.size());
for (Future<Connection> connection : connCreatorsFuture) {
    // will wait until this connCreator finishes.
    connections.add(connection.get());
}
return connections;

Upvotes: 0

Archer
Archer

Reputation: 5147

According to this javadoc Future<V> has .get() method that returns an object of type of V. You should invoke that method to receive the result of Future execution. It's safe to invoke it from callee thread.

Upvotes: 0

GreyBeardedGeek
GreyBeardedGeek

Reputation: 30088

Take a look at ThreadPool's invokeAll method - it takes a collection of Callables and returns a list of Futures.

Edit: the advantage of using invokeAll over simply submitting your tasks one at a time and putting the Futures in your own list is that invokeAll will return only after all of the tasks complete, so you don't have to keep checking all of the Futures to see if they have completed.

Upvotes: 2

Related Questions