5

我有一个 web 服务,它在初始化时使用数据源实例化单个QueryRunner 。它通过将这个QueryRunner对象作为 servlet 上下文属性传递给来自 webapp 使用的多个不同 servlet 的所有 servlet 请求。IE:

// in servlet context listener (on app initialization)
QueryRunner myQueryRunner = new QueryRunner(myDataSource);
myServletContext.setAttribute("queryRunner", myQueryRunner);

// in the servlets
QueryRunner myQueryRunner = (QueryRunner) myServletContext.getAttribute("queryRunner");
myQueryRunner.query(myStoredProcedure, handler, params)

我试图弄清楚这是否是一个瓶颈。servlet 是否应该为QueryRunner每个请求都实例化一个新的?

在四处寻找答案时,我还发现了这个AsyncQueryRunner。但我只是变得更加困惑,因为QueryRunnerAsyncQueryRunner的 API 文档中的解释说的完全一样。

我查看了这里的示例,似乎应该用每个请求实例化它,但我不确定这是否仅仅是因为它是示例代码。

换句话说,在使用 DBUtils 时,QueryRunner我应该:

  1. QueryRunner为每个请求使用单个实例?(我现在在做什么)
  2. QueryRunner用每个 servlet 请求实例化一个新的?
  3. AsyncQueryRunner为每个请求使用单个实例?
4

1 回答 1

6

QueryRunner 是一个线程安全类,因为它是无状态的,因此您可以在多线程环境中使用单个实例而不会出现任何问题。

所有方法都是自包含的,因此无需同步方法访问,因此您也可以排除瓶颈。

我在生产环境中使用它没有问题,但我的实现遵循“用每条语句实例化一个新的 QueryRunner”的模式,因为它是一个没有状态的委托类,所以没有繁重的初始化和堆消耗,我避免使用单例或其他共享实例存储此类类型。

AsyncQueryRunner 也是线程安全的,但它的用途和用法完全不同(参见http://commons.apache.org/proper/commons-dbutils/examples.html)。它用于为长时间运行的语句创建非阻塞调用。如果您的业务层需要异步,它可能会很有用。

综上所述:

  • 使用来自多个线程的单个 QueryRunner 实例(每个请求一个线程?)没有反指示,但也没有优势,但是在某处需要一些代码来管理这个实例
  • 为每个线程甚至是要通过它委托的每个语句使用新的 QueryRunner 实例有两个主要优点:简单和本地化的使用,如果不需要它们,内存中没有实例。
  • AsyncQueryRunner 需要对查询响应进行繁琐的管理,因此只有在业务代码中需要异步行为时才使用它。
于 2014-01-19T19:22:48.040 回答