19

我有一个由大约 15 个方法组成的 Java 程序。而且,这些方法在程序执行过程中被非常频繁地调用。目前,我正在每个方法中创建一个新连接并在它们上调用语句(数据库设置在网络上的另一台机器上)。

我想知道的是:我是否应该在主方法中只创建一个连接并将其作为参数传递给所有需要连接对象的方法,因为它会显着减少程序中连接对象的数量,而不是创建并在每种方法中非常频繁地关闭连接。

我怀疑我在当前设计中没有非常有效地使用资源,并且考虑到该程序将来可能会增长很多,还有很大的改进空间。

4

5 回答 5

23

是的,您应该考虑重新使用连接,而不是每次都创建一个新连接。通常的程序是:

  • 猜测一下您的数据库可以合理地处理多少个同时连接(例如,从数据库机器上的每个 CPU 2 或 3 个开始,直到您发现这太少或太多——这往往取决于磁盘的方式-绑定您的查询)
  • 创建这么多连接的:本质上是一个类,您可以在每个方法开始时请求“下一个空闲连接”,然后在每个方法结束时“传回”到池
  • 如果有可用连接,您的 getFreeConnection() 方法需要返回一个免费连接,否则(1)创建一个新连接,直到您决定允许的最大连接数,或者(2)如果已经创建了最大值, 等待一个变得自由
  • 我建议使用 Semaphore 类来管理连接;实际上,我的网站上有一篇关于使用信号量管理资源池的简短文章,并附有一个示例,我认为您可以适应您的目的

几个实际的考虑:

  • 为获得最佳性能,您需要注意不要在实际未使用连接运行查询时“占用”连接。如果您从池中获取一次连接,然后将其传递给各种方法,则需要确保您不会意外地这样做。
  • 不要忘记将您的连接返回到池中!(尝试/终于是你的朋友在这里......)
  • 在许多系统上,您不能“永远”保持连接打开:操作系统将在最长一段时间后关闭它们。因此,在您的“将连接返回到池”方法中,您需要考虑“退出”已经存在很长时间的连接(建立一些记忆机制,例如通过在实际 JDBC 周围有一个包装器对象可用于存储此类指标的连接对象)
  • 您可能需要考虑使用准备好的语句。
  • 随着时间的推移,您可能需要调整连接池大小
于 2009-01-23T05:10:28.273 回答
9

您可以传递连接,也可以更好地使用 Jakarta Database Connection Pooling 之类的东西。 http://commons.apache.org/dbcp/

于 2009-01-23T03:15:52.700 回答
8

您应该为此使用连接池。

这样你就可以请求连接并在完成后释放它并将其返回到池中

如果另一个线程想要一个新连接并且该连接正在使用中,则可以创建一个新连接。如果没有其他线程正在使用连接,则可以重复使用该连接。

这样,您可以以某种方式离开您的应用程序(而不是到处传递连接),并且仍然可以正确使用资源。

不幸的是,一流的 ConnectionPools 在独立应用程序中不是很容易使用(它们是应用程序服务器中的默认设置),可能一个微容器(例如 Sping)或一个好的框架(例如 Hibernate)可以让您使用一个。

不过,从头开始编写代码并不难。

:)

这个谷歌搜索将帮助您找到更多关于如何使用的信息。

快速浏览

于 2009-01-23T03:14:36.573 回答
4

许多 JDBC 驱动程序会为您执行连接池,因此在这种情况下进行额外的池化几乎没有优势。我建议您查看 JDBC 驱动程序的文档。

连接池的另一种方法是

  • 为所有具有同步访问的数据库访问建立一个连接。这不允许并发,但非常简单。
  • 将连接存储在 ThreadLocal 变量中(覆盖 initialValue()) 如果有少量固定数量的线程,这很有效。

否则,我建议使用连接池。

于 2009-01-24T13:14:08.453 回答
1

如果您的应用程序是单线程的,或者从单个线程执行所有数据库操作,则可以使用单个连接。假设您出于任何其他原因不需要多个连接,这将是迄今为止最简单的实现。

根据您的驱动程序,在线程之间共享连接也可能是可行的 - 如果您相信您的驱动程序不会对其线程安全性撒谎,这也可以。有关详细信息,请参阅您的驱动程序文档。

通常,“Connection”下面的对象不能安全地从多个线程中使用,因此通常不建议在线程之间共享 ResultSet、Statement 对象等 - 到目前为止,最好的策略是在创建它们的同一线程中使用它们;这通常很容易,因为这些对象通常不会保存太久。

于 2009-01-24T12:18:43.853 回答