Java 线程不会暂停 I/O 操作

标签 java networking multithreading udp blocking

我的印象是,在 Java 中,线程会暂停并让其他线程有机会在阻塞 I/O 操作期间做一些工作(如 Socket.read() 或 DataGramsocket.receive() )。由于某种原因,在我的多线程网络应用程序中,对 receive() 的调用导致我所有其他线程饿死(调用 receive() 的线程正在成为一个大老板,永远不会放弃控制,因此永远阻塞!)

为什么会这样?我曾经拥有完全相同的应用程序,但它不是基于 UDP 的,而是基于 TCP 的。如果阻塞时间过长,Socket.read() 总是会暂停线程并允许其他线程工作一段时间。

-- 额外信息 -- 我的自定义线程的 TCP 版本是这段代码: http://www.dwgold.com/code/proxy/proxyThread.java.txt

我的新代码(UDP 版本)几乎相同,但做了一些修改以使用 UDP 方法和样式。然后我创建了两个这样的线程并在两个线程上调用 start。在 UDP 版本中,第一个线程总是阻塞并且从不让另一个线程工作。

最佳答案

看来您正在使用 InputStream,并且根据 the JDK docs for InputStream.read() ,读取 block 与您所描述的完全一样——直到收到数据、到达文件末尾或引发异常。

所以对我来说,问题是:为什么您的代码的 TCP 版本允许 block 被中断?这似乎没有任何意义。也许您的 TCP 代码将读取分解为离散的、足够短的突发,线程有机会在对 read() 的单独调用之间跳转?

进一步观察,我发现区别在于您的代码的 TCP 版本通过 Socket 提供的 InputStream 接收数据,而您的代码的 UDP 版本直接从 DatagramSocket 自己的 receive() 方法接收数据。所以我认为这只是两者(InputStream.read 和 DatagramSocket.receive)提供的功能之间的根本区别。你有没有想过使用DatagramPacket.setSoTimeout在套接字的接收 block 上设置超时,然后在调用超时的 receive() 抛出 SocketTimeoutException 时捕获它?您应该能够实现它以实现您想要的。

更新:进一步观察,似乎the DatagramSocket.receive method is synchronized .因此,解释您所看到的行为的方法是,您正在启动两个试图使用同一个 DatagramSocket 实例的线程——如果两个线程试图在同一个 DatagramSocket 实例上执行 receive() ,一个将阻止实例直到它完成,另一个将被阻止。 (还有 a post on the Sun forums that describes this。)这可能就是正在发生的事情——您正在为两个线程重用相同的 DatagramSocket?

关于Java 线程不会暂停 I/O 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1784570/

相关文章:

Java 8 Locale.getDefault() 返回 null

java - Spring-通过链接传递参数

.net - 捕获 VPN 使用统计信息

c++ - 1 个线程工作但导致调用方法不返回的线程问题

java - 在没有控制台的情况下启动 java 程序

java - 如何控制第 3 方库中的日志记录

ruby - 在 Ruby 中构建 UDP 数据报

postgresql - kubernetes 如何将 pod 暴露给集群机器之外的东西?

java - android 在新线程中运行类

java - javafx-fxml 中不同类的持续标签更新