1

我需要创建一堆到不同主机的 JMX 连接。我正在尝试并行创建这些连接。现在在这方面的表现要好得多。

我已经将“主机和端口”条目的集合传递给该方法。对于每个条目,将创建一个连接。

现在我正在提交创建与多个线程的连接的任务。但我不知道如何返回并存储线程创建的连接对象。

代码是这样的,

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.

}
4

4 回答 4

2

看一下 ThreadPool 的 invokeAll 方法——它接受一个 Callable 集合并返回一个 Future 列表。

编辑:与简单地一次提交一个任务并将 Futures 放在您自己的列表中相比,使用 invokeAll 的优势在于,invokeAll 只会在所有任务完成后返回,因此您不必继续检查所有 Futures看看他们是否已经完成。

于 2013-01-10T19:16:04.283 回答
1

一旦每个线程(您的 ConnectionCreator)创建了一个连接,它就需要使用某种单例将句柄注册到新创建的连接。如果您在 EJB 容器中运行,这很容易通过会话 bean 完成。本质上,这个会话 bean 可以成为“连接池”。在连接创建器中,您可以执行以下操作(为简洁起见,我不包括异常处理和您应该已经做的其他事情):

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 );

然后在您的 ConnectionPoolBean 中,您拥有一个连接对象的集合。您应该在这些对象中注册和取消注册方法——以及可能的 getConnection... 等等。希望有帮助。

于 2013-01-10T19:19:31.447 回答
0

根据this javadoc Future<V>has .get()method that return an object of V. 您应该调用该方法来接收Future执行结果。从被调用线程调用它是安全的。

于 2013-01-10T19:21:19.533 回答
0

您可以使用ExecutorCompletionService来运行连接打开器,并按照首先打开连接的顺序获取它们:)

因此,使用您的代码,它将类似于

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;

希望这可以帮助 :)

编辑

重要提示:您不能使用 CompletionService 和Executor#submit. 问题是您的调用Future#get() 必须在另一个循环中完成,否则您将阻塞您的线程,直到刚刚提交的可调用对象完成。所以:

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;
于 2013-01-10T20:15:15.700 回答