我有一个webservice,在初始化时使用数据源实例化单个QueryRunner。它将这一个QueryRunner
对象用于来自webapp使用的多个不同servlet的所有servlet请求,方法是将其作为servlet上下文属性传递。即:
// 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。但我更加困惑,因为QueryRunner和AsyncQueryRunner的API文档中的解释说的完全相同。
我查看了示例here,似乎应该对每个请求进行实例化,但我不确定这是否只是因为它是示例代码。
换句话说,当我使用DBUtils QueryRunner
时:
QueryRunner
个实例? (我是什么
现在这样做)QueryRunner
?AsyncQueryRunner
个实例?答案 0 :(得分:5)
QueryRunner是一个线程安全类,因为它是无状态的,因此您可以在多线程环境中使用单个实例而不会出现任何问题。
所有方法都是自包含的,因此不需要同步方法访问,因此您也可以排除瓶颈。
我在生产环境中使用它没有问题,但我的实现遵循“用每个语句实例化一个新的QueryRunner”的模式,因为它是一个没有状态的委托类,所以没有繁重的初始化和没有堆消耗,我避免使用单例或其他用于存储此类类的共享实例。
AsyncQueryRunner也是线程安全的,但其目的和用法完全不同(请参阅http://commons.apache.org/proper/commons-dbutils/examples.html)。它用于为长时间运行的语句创建非阻塞调用。如果您的业务层需要异步,那么它可能很有用。
总结: