我正在编写多线程套接字服务器。我使用 nioServerSocketChannel
来接受连接。然后我正在阅读和写作(在单独的线程中)以socketChannel
使用bufferedreader
和打印作家。问题是PrintWriter
锁定并等待flush()
命令。它阻塞线程直到BufferedReader
接收到数据。
2 回答
这表明接收器读取缓慢。这就是阻塞 I/O 的工作原理。如果您想要非阻塞 I/O,那么您已经是其中的一部分,因为您已经在使用 NIO。虽然我真的完全看不出在阻塞模式下使用 NIO 的意义。
正如@EJP 所说,这基本上就是阻塞 IO 的工作方式。事实上,这个问题在任何有生产者和消费者的架构中都是固有的。如果生产者生产的东西(在这种情况下是文本输出行)比消费者消费它的速度快,那么生产者最终不得不阻塞。
你怎么能解决这个问题?首先是一些一般的东西。
如果从长远来看,生产者生产的东西比消费者消费的快,那么你就处于困境和困境之间。您必须要么降低生产者的生产速度,加快消费者的消费速度,要么减少管道中的开销以达到相同的效果。没有其他工作。
如果速率不匹配只是暂时的,您可以通过向管道添加一些额外的缓冲来“掩盖裂缝”。如果之间的连接有一些缓冲能力,你也许可以增加它。或者,您可以在生产者或消费者端添加额外的缓冲。
以下是一些可能对您的特定情况有所帮助的事情。
减少您在生产者线程中编写的内容量。
在消费者线程中做更少的工作,或者分析/调整它们以更快地完成工作。
不要使用套接字在同一个 JVM 中的两个线程之间进行通信。如果可以安排,请使用 Java PipeInputStream / PipeOutputStream 对,或滚动您自己的等效项。(如果您使用套接字,读取和写入涉及系统调用、将数据复制到内核缓冲区中或从内核缓冲区中复制出来等等。)
如果通信必须在 JVM 之外进行,请确保
Buffered*
对底层流使用包装器,以减少在读/写时进行的系统调用的数量。