我使用Java 8,Hibernate 5.1.0.Final和Guice 4.1.0。
@Inject
private Provider<ExampleDAO> exampleDAOProvider;
public void test(){
ExecutorService threadPool = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++)
threadPool.execute(new Runnable() {
@Override
public void run() {
logger.info(exampleDAOProvider.find(1l));
}
});
threadPool.shutdown();
}
每个test()
方法执行将在pg_stat_activity
中产生更多10(线程池大小)行。它们是简单的select * from
查询,具有idle in transaction
状态且永不消失。所以我达到hibernate.c3p0.max_size
限制,我的应用程序停止使用数据库。
数据库模块:
public class ExampleModule extends PrivateModule {
@Override
public void configure() {
install(new JpaPersistModule("example-persistence-unit").properties(jpaProperties()));
bind(ExampleDAO.class).to(ExampleDAOImpl.class);
expose(ExampleDAO.class);
Key<PersistFilter> key = Key.get(PersistFilter.class, ExamplePersistenceUnit.class);
bind(key).to(PersistFilter.class);
expose(key);
}
}
我已经尝试@Inject Provider<ExampleDAO> exampleDAOProvider
进入任务类代码,但它没有改变任何东西。如果我@Inject exampleDAO
,那么我会遇到并发问题(ConcurrentModificationException
),因为它使用相同的EntityManager
。
如果我在没有多线程的情况下使用@Inject Provider<ExampleDAO> exampleDAOProvider
或直接@Inject ExampleDAO exampleDAO
,它可以很好地工作并且连接会被释放。
为什么会这样?如何在多线程代码中发布连接?