Java 如何保持固定的连接数

Java 如何保持固定的连接数,java,multithreading,performance,network-programming,threadpool,Java,Multithreading,Performance,Network Programming,Threadpool,我是Java新手,但对一般编程并不陌生 这种情况下,我一次最多可以有n个连接,打开和关闭一个连接的成本非常高 我希望重用相同的n个连接,并希望在集合中保留一些内容 当一个请求到来时,我拿起它的连接,做我的工作并返回连接而不关闭。当下一个请求到来时,我会选择下一个可用的连接 当所有连接都在使用中,并且有请求出现时,我只需等待连接可用 最干净的java解决方案是什么。我不需要代码,我只需要一些想法来探索。可能是一些框架已经做到了这一点,可能是一些java类已经提供了这一功能 任何想法都将不胜感激。我

我是Java新手,但对一般编程并不陌生

这种情况下,我一次最多可以有n个连接,打开和关闭一个连接的成本非常高

我希望重用相同的n个连接,并希望在集合中保留一些内容

当一个请求到来时,我拿起它的连接,做我的工作并返回连接而不关闭。当下一个请求到来时,我会选择下一个可用的连接

当所有连接都在使用中,并且有请求出现时,我只需等待连接可用

最干净的java解决方案是什么。我不需要代码,我只需要一些想法来探索。可能是一些框架已经做到了这一点,可能是一些java类已经提供了这一功能


任何想法都将不胜感激。

我建议您使用连接池。在这种情况下,如果要将连接用于多个任务,请分别编写它们并将它们放入池中。 需要时从池中获取连接。完成后,将其推回池中。通过这种方式,连接将是线程安全的,并且可以避免不一致性。
此外,打开和关闭连接将导致资源紧张。

您可以使用具有固定线程数的Executor服务

ExecutorService service = Executors.newFixedThreadPool(n);
您可以创建一个类连接,它将创建一个连接对象并返回它

class Connection implements Callable<Connection> {

    @Override
    public Connection call() {
        // Logic to get the connection
        return new Connection();
    }
}
类连接实现了可调用{
@凌驾
公共连接呼叫(){
//获取连接的逻辑
返回新连接();
}
}
然后提交任务并从池中获取未来的连接对象

Future<Connection> future = service.submit(new Connection());
Connection conn = future.get();
Future=service.submit(新连接());
连接conn=future.get();

使用HTTP核心NIO或Netty之类的框架来实现这一点。对于示例实例HTTPCore NIO,您可以创建一个工作线程组来连接后端,如下所示

ProxyConnPool connPool = createConnectionPool(connectingIOReactor);
connPool.setMaxTotal(100);
connPool.setDefaultMaxPerRoute(20);

private static ProxyConnPool createConnectionPool(final ConnectingIOReactor connectingIOReactor)
                                                                                                    throws KeyManagementException,
                                                                                                    KeyStoreException,
                                                                                                    NoSuchAlgorithmException,
                                                                                                    CertificateException,
                                                                                                    FileNotFoundException,
                                                                                                    IOException {
        ProxyConnPool proxyConnPool = null;

        if (SECURE_BACKEND) {
            clientSSLContext =
                               SSLUtil.createClientSSLContext(TRUST_STORE_LOCATION,
                                                              TRUST_STORE_PASSWORD);

            BasicNIOConnFactory connectionFactory =
                                                    new BasicNIOConnFactory(
                                                                            clientSSLContext,
                                                                            null,
                                                                            ConnectionConfig.DEFAULT);

            proxyConnPool = new ProxyConnPool(connectingIOReactor, connectionFactory, 5000);
        } else {
            proxyConnPool = new ProxyConnPool(connectingIOReactor, ConnectionConfig.DEFAULT);
        }

        return proxyConnPool;
    }
您可以找到和的示例代码

在Netty中,代码与此类似

// Configure the bootstrap.
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
希望这有帮助。快乐编码

当一个请求到来时,我拿起它的连接,做我的工作并返回连接而不关闭。当下一个请求到来时,我会选择下一个可用的连接

我将使用一个简单的
阻塞队列
,它由所有线程共享

final BlockingQueue<Connection> connectionQueue = new LinkedBlockingQueue<Connection>();
当一个线程去获取一个连接时,它将从队列中获取一个
连接
,如果没有立即可用的连接,它将等待一个连接。在使用
连接后
会将其返回到队列,以便下一个线程使用

// this will wait if there are no connections available
Connection connection = queue.take();
try {
   useTheConnection(connection);
} finally {
   // after we are done add it back to the queue
   queue.put(connection);
}
所有这一切的棘手部分是当您在套接字上遇到某种网络异常时。您的线程需要正确关闭
连接
,然后向队列中添加一个新连接。可能是这样的:

// this will wait if there are no connections available
Connection connection = queue.take();
try {
   useTheConnection(connection);
} catch (Exception e) {
   // assume the connection is bad
   try {
      connection.close();
   } catch (Exception e2) {
      // ignore any exceptions here
   }
   // start a new fresh connection to add back to our queue
   connection = new Connection();
} finally {
   // after we are done add it back to the queue
   queue.put(connection);
}

连接到什么?类似于连接池数据库提供的…这些是到外部服务器的套接字连接,因此,您有一个n个连接。放置分发连接的连接处理程序。如果没有可用的线程,则对其进行排队。仅仅为了创建连接而启动线程是浪费的,并且这里没有任何东西可以将它们聚集在一起。
// this will wait if there are no connections available
Connection connection = queue.take();
try {
   useTheConnection(connection);
} catch (Exception e) {
   // assume the connection is bad
   try {
      connection.close();
   } catch (Exception e2) {
      // ignore any exceptions here
   }
   // start a new fresh connection to add back to our queue
   connection = new Connection();
} finally {
   // after we are done add it back to the queue
   queue.put(connection);
}