从 Java 发起的 DB 查询是否总是阻塞 I/O?

Oll*_*liP 6 java multithreading scheduling blocking

假设一些阻塞 I/O 是用 Java 完成的,例如长时间运行的数据库查询。Java 中是否有一种方法可以让某些 Java 数据库驱动程序告诉 JVM 调度程序该调用已离开 JVM,现在正在由某个外部系统处理?然后,JVM 可以将为数据库查询提供服务的线程分配给其他操作,直到数据库的回复到达。这样,阻塞数据库查询将有效地变为非阻塞。

只是想知道这是否可以在一般的 JVM 上完成。我从事 Java 工作很多年了,但我承认我不知道 Java 调度程序在这种情况下在做什么。

Gra*_*ray 7

假设一些阻塞 I/O 是用 Java 完成的,例如长时间运行的数据库查询。Java 中是否有一种方法可以让某些 Java 数据库驱动程序告诉 JVM 调度程序该调用已离开 JVM,现在正在由某个外部系统处理?

呃,不。线程的全部意义在于,如果它们阻塞,则可以调度另一个线程来接管处理器或其他资源。您不希望 JVM 以某种方式使用保存所有 JDBC 状态、堆栈帧、变量等的同一线程。您确实希望它使用相同的处理器和其他系统资源来执行不同线程的任务。请记住,线程的开销相对较低。在现代系统上,当 JVM 中有 1000 个这样的堆栈时,您可能会开始遇到问题,主要是因为它们每个都分配了固定的堆栈空间区域。

作为程序员,我们优化这一点的方法是使用多个线程、线程池、数据库连接池等。然后,作为查询块,其他线程和查询可以并行工作,以最大化系统吞吐量。

  • @Oliver主要的一点是:没有Java不会做类似的事情,并且以这种方式实现某些东西的唯一方法将涉及大量额外的复杂性而没有太多收益。更高级别的异步 IO(即通过驱动程序/框架)是此处的方法。 (3认同)
  • 绝对正确,这将是一个非常非常可怕的想法——尽管有一些有趣的可能性。那么有人对人们实际上实现了类似的东西感到惊讶吗?[纤维](http://en.wikipedia.org/wiki/Fiber_(computer_science))。不过只在 Raymond Chen 的一篇文章中看到过它们。据我所知,没有人为 Java/JVM 做过类似的事情。 (2认同)
  • 我不确定我能否让大家理解这一点。如果线程由于某些数据库查询而被阻塞,那么线程池就会丢失该线程。因此,如果您的线程池有 10 个线程,并且您启动了 10 个数据库查询,然后分叉了一个新线程,则在第一个数据库查询返回之前,不会处理新线程。这就是拥有一个可以产生的数据库驱动程序的要点,请参阅 stackoverflow 上的 f.ex 这个问题:http://stackoverflow.com/questions/17953269/go-routine-blocking-the-others-one (2认同)
  • 如果您担心线程池中的线程阻塞@OliverPlow,那么您应该使用动态调整大小的线程池。池大小优化并非易事,但您无法摆脱保留其堆栈和其他状态所需的线程。如果您以某种方式将线程与此状态分开,那么就线程开销而言,您就不会剩下太多了。 (2认同)