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

时间:2018-07-29 16:50:08

标签: java

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

过了一会儿,我开始深入研究Java套接字(我想JDBC是在它们之上构建的),并意识到也没有任何事件处理。提供非阻塞读取的唯一方法是通过available()方法,但这效率很低,因为必须在循环中定期对其进行检查。

据我所知,中断是PC中最基本的事情。它从硬件降到操作系统。在Java中,可以从Socket读取值将其实现为事件驱动的方法。

现在,我的问题是,我是否缺少某些东西,并且存在某种变通方法,或者Java中的当前体系结构真的是每个阻塞操作一个线程吗?,如果是,则为'效率低下吗?

2 个答案:

答案 0 :(得分:1)

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

多线程应用程序的基本方案是,在等待阻塞线程时会使用多个线程,这会导致过多的等待。这里“太多”的定义完全取决于您,但是总的来说,这就是通过更好地利用资源来实现更好的性能的方法。

但是,Java中的线程工作方式存在一些限制。大多数(如果不是全部)都是在线程被阻塞在Java“外部”的某个地方时,例如在OS调用或外部(本机)库中。从理论上讲,如果本机代码阻止了线程,则Java对此无能为力。通常,除非本地代码存在错误,否则这应该不是问题。

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

自Java 7起,还支持非阻塞I / O(NIO)。这几乎就是您所描述的。 I / O已卸载到OS,因此您的操作将立即返回,并且在操作完成时会得到回调。但是,并非所有库都支持NIO。对于我的工作,我从来没有理由使用它,因为我总是可以用我的线程至少实现同样的效果。

答案 1 :(得分:1)

如果问题是“ Java中的当前体系结构实际上是否是每一个阻塞操作一个线程”,而用“阻塞操作”表示“数据库操作”,那么答案是否定的。当前,大多数可用于Java的数据库驱动程序都是基于jdbc的,并且以这种方式工作。但是有可用的替代方法(https://spring.io/blog/2016/11/28/going-reactive-with-spring-data),还有更多可用的替代方法( https://blogs.oracle.com/java/jdbc-next:-a-new-asynchronous-api-for-connecting-to-a-databasehttps://dzone.com/articles/spring-5-webflux-and-jdbc-to-block-or-not-to-block)。有关其工作原理,请参见How is ReactiveMongo implemented so that it is considered non-blocking?

对于jdbc,也有一些方法可以包装jdbc调用(Wrapping blocking I/O in project reactorSpring webflux and reading from database)和采用这种方法的项目(https://dzone.com/articles/myth-asynchronous-jdbc