2013-02-15 76 views
3

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

// 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文档中的解释说的完全一样。

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

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

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

我想弄清楚这是否是一个瓶颈。这是不可能的。QueryRunner是一个线程安全的类,您可以为所有请求使用一个QueryRunner。 AsyncQueryRunner使用ThreadPool来处理每个查询,但它不是正常情况,它只用于长查询花费。 – 2015-04-09 05:57:18

回答

4

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

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

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

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

结论:从多个线程(?每个请求一个线程)

  • 采用单QueryRunner实例没有counterindication也没什么adavantages,但需要的代码一点点的地方来管理这种情况下
  • 为每个线程使用新的QueryRunner实例,甚至为每个要通过它委派的语句使用新的QueryRunner实例有两个主要优点:简单和本地化的使用,如果不需要它们,则内存中没有实例。
  • AsyncQueryRunner需要繁琐的查询响应管理,因此只有在业务代码中需要异步行为时才能使用它。