为什么 Java Socket 不支持中断处理?



我一直在思考为什么JDBC只阻止操作,以及为什么我不能将一些侦听器设置为假设的事件处理程序onResultSetArrived(ResultSet-rs(。为什么我必须为每个JDBC查询阻塞一个线程。

过了一段时间,我深入研究了Java套接字(我想JDBC是在它们之上构建的(,并意识到也没有任何事件处理。提供非阻塞读取的唯一选项是通过available((方法,但这是非常低效的,因为它必须在循环中定期检查。

据我所知,中断是PC中最基本的东西。它从硬件一直到操作系统。在Java中,它可以通过从Socket读取值来实现为事件驱动的方法。

现在,我的问题是我是不是遗漏了什么,并且存在一些变通方法,或者Java中的当前体系结构真的是一个线程一个阻塞操作如果是,这不是效率低下吗?

在Java中,可以有许多线程。线程一直在做它的事情,直到它在某个地方被阻塞(通常是在互斥对象或I/O操作上(。当然,这不会阻塞其他线程。

多线程应用程序的基本场景是使用多个线程,而等待阻塞的线程会导致太多的等待。这里"太多"的定义完全取决于您,但总的来说,这就是您如何通过更好地利用资源来获得更好的性能。

然而,Java中的线程工作方式存在一些限制。大多数(如果不是全部的话(都是当线程在Java"外部"的某个地方被阻塞时,比如在操作系统调用或外部(本机(库中。从理论上讲,如果本机代码阻塞了一个线程,Java就无法对此采取任何措施。通常,除非本机代码有错误,否则这应该不会成为问题。

所以,在阻塞JDBC响应的情况下,您将创建一个新线程,该线程将在第一个线程等待数据库完成时执行其他工作。或者,您可以制作一个线程来执行JDBC。除了操作系统的限制外,您可以(使用监听器等(完全按照自己的意愿制作它。因此,这是可能的,但JDBC驱动程序可能不会提供开箱即用的功能。核心Java中已经有很多基础设施,您可能会发现它们很有用(线程池、工作线程、同步集合(。但是,与任何多线程一样,您需要非常小心地同时访问来自不同线程的数据。

自Java7以来,还支持非阻塞I/O(NIO(。这几乎正是你所描述的。I/O被卸载到操作系统,因此您的操作会立即返回,并且在操作完成时会得到回调。然而,并不是所有的库都支持NIO。对于我的工作,我从来没有理由使用它,因为我总是可以用我的线程实现同样的东西,至少同样好。

如果问题是"Java中的当前体系结构是否真的是每一个阻塞操作一个线程",而"阻塞操作"指的是"数据库操作",那么答案是否定的。目前可用于Java的大多数数据库驱动程序都是基于jdbc的,并以这种方式工作。但也有可用的替代方案(https://spring.io/blog/2016/11/28/going-reactive-with-spring-data)还有更多(https://blogs.oracle.com/java/jdbc-next:-新的同步api用于连接到数据库,https://dzone.com/articles/spring-5-webflux-and-jdbc-to-block-or-not-to-block)。有关其工作原理,请参阅ReactiveMongo是如何实现的,以便将其视为非阻塞的?

对于jdbc,还有一些方法可以包装jdbc调用(包装项目reactor中的阻塞I/O、Spring-webflux和从数据库读取(和采用这种方法的项目(https://dzone.com/articles/myth-asynchronous-jdbc)

最新更新