【问题标题】:Should a single thread only acquire a single connection from a connection pool?单个线程是否应该只从连接池中获取单个连接?
【发布时间】:2019-07-30 20:32:44
【问题描述】:

我将 ORMLite (Java) 与 HikariCP 一起使用,并且我有很多异步调用的代码,即 CompletableFuture.supplyAsync(Supplier)。在供应商内部,我在这些任务中对不同的 ORMLite Dao 对象进行了各种调用。我遇到了一个死锁场景,发现增加连接池的大小似乎已经解决了这个问题。

经过一番研究,我发现这是一个有据可查的问题。查看了here提供的信息:

“每个线程都在等待第二个数据库连接,由于所有线程都被阻塞,因此没有一个可用。”

这引起了我的注意。看ORMLite源码的时候发现,每调用一个Dao方法,都会获取一个连接。就我而言,我在通过CompletableFuture 创建的每个异步任务中调用多个 Dao 方法,这让我想到了我的问题。

我的理解是我应该只在每个线程中获取一个连接,那么有没有办法用 ORMLite 做到这一点?记住我调用了不同的 Dao 对象并做了一些进一步的研究,Dao#callBatchTasks(Callable) 引起了我的注意,但我不确定我是否可以调用 Callable 中的不同 Dao 对象。还是我的逻辑有缺陷,或者我的文章中缺少一些基本的东西?

【问题讨论】:

  • 赞成告诉存在像 OrmLite 这样的东西。

标签: java multithreading ormlite


【解决方案1】:

我发现每调用一个Dao方法,都会获取一个连接

如果ORMLite 需要访问数据库,它需要获得连接,对吧?有什么地方做得不对吗?

我的理解是我应该只在每个线程中获取一个连接,那么有没有办法用 ORMLite 做到这一点?

我不认为有什么说一个线程不能打开多个数据库连接。只要在您完成te操作时它们都关闭,那么我认为这很好。如果您正在查询都存在于同一个数据库中的不同 DAO,那么只要您完成了连接,您实际上就可以每次都重用该连接。 IE。如果您使用打开的连接对结果进行分页,然后在中间查询另一个表,那么这可能会搞砸游标。但是,如果您先执行dao1.queryAll(),然后执行dao2.queryAll(),则可以使用相同的连接,因为第一个查询已经完成。

但是,如果您使用的是连接池,则该池应在 ORMLite 的 ConnectionSource 的帮助下为您进行连接管理。如果需要,该池应该为您创建一个新连接,否则会重用旧连接。对数据库连接设置限制有点奇怪。

Dao#callBatchTasks(Callable) 引起了我的注意,但我不确定是否可以调用 Callable 中的不同 Dao 对象。

你可以调用不同的dao对象,只要它们都在同一个数据库上。实际上,您可以调用连接到不同数据库的 dao,但您无法保证数据库之间的事务。

例如,如果您执行以下操作。

  1. 您拨打dao1.callBatchTasks(callable)
  2. 在您的 Callable 中,您调用 dao2.delete(entity1) 可以正常工作。
  3. 仍在Callable 中,您调用dao2.delete(entity2) 会引发。
  4. dao1 事务将被回滚,但entity1 仍将被删除。

【讨论】:

  • 抱歉这个@someone的延迟。
【解决方案2】:

你在声明中引用的场景

每个线程都在等待第二个数据库连接,并且没有 将变得可用,因为所有线程都被阻塞了。

只有当线程持有连接 A 的锁并试图获取连接 B 时才会导致死锁,而连接 B 可能被另一个可能试图获取连接 A 的线程持有。只要你不是在试图“抓住”另一种资源的同时“持有”一种资源,你应该很好。

【讨论】:

  • 这是对死锁位条件的正确描述,与问题无关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-16
  • 2023-02-01
  • 2019-07-07
  • 2011-05-28
  • 1970-01-01
相关资源
最近更新 更多