PrintWriter 等待flush()
我正在编写多线程套接字服务器。我使用 nio 的 ServerSocketChannel 来接受连接。然后,我使用 bufferedreader 和 print writer 读取和写入(在单独的线程中)socketChannel。 问题是 PrintWriter
锁定并等待 flush()
命令。它会阻塞线程,直到 BufferedReader 接收数据。
I'm writing multithreaded socket server. I use nio's ServerSocketChannel
for accepting connections. Then Ii'm reading and writing (in separate threads) to socketChannel
using bufferedreader
and print writer.
The problem is that PrintWriter
locks and waits on flush()
command. It blocks thread until the BufferedReader
receive data.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这表明接收器正在缓慢读取。这就是阻塞 I/O 的工作原理。如果您想要非阻塞 I/O,那么您已经成功了,因为您已经在使用 NIO。虽然我真的完全看不出在阻塞模式下使用 NIO 的意义。
That indicates that the receiver is slow reading. That's how blocking I/O works. If you want non-blocking I/O you're already part of the way there, as you are already using NIO. Although I really don't see the point of using NIO in blocking mode at all.
正如 @EJP 所说,这基本上就是阻塞 IO 的工作方式。事实上,这个问题是任何拥有生产者和消费者的架构所固有的。如果生产者生产内容(在本例中为文本输出行)的速度比消费者消费它的速度快,那么生产者最终必须阻塞。
你怎么解决这个问题?首先是一些一般性的东西。
如果生产者生产东西的速度快于消费者消费的速度,从长远来看,你就会陷入进退两难的境地。您必须降低生产者的生产速度,加快消费者的消费速度,或者减少管道中的开销以达到相同的效果。其他都不起作用。
如果速率不匹配只是暂时的,您可以通过向管道添加一些额外的缓冲来“掩盖裂缝”。如果之间的连接具有一定的缓冲能力,您也许可以增加它。或者,您可以在生产者或消费者端添加额外的缓冲。
以下是一些可能对您的特定情况有帮助的事情。
减少您在生产者线程中编写的内容量。
在消费者线程中减少工作量,或者分析/调整它们以更快地完成工作。
不要使用套接字在同一 JVM 中的两个线程之间进行通信。如果您可以安排它,请使用 Java PipeInputStream / PipeOutputStream 对,或推出您自己的等效项。 (如果使用套接字,则读写涉及系统调用、将数据复制到内核缓冲区或从内核缓冲区复制数据等等。)
在通信必须超出 JVM 的情况下,确保对底层流使用 Buffered* 包装器,以减少读/写时进行的系统调用数量。
As @EJP says, that is basically the way that blocking IO works. Indeed, this problem is inherent in any architecture where you have a producer and a consumer. If the producer produces stuff (in this case lines of text output) faster than the consumer can consume it, then the producer eventually has to block.
How can you solve this? First some general stuff.
If the producer produces stuff faster than the consumer consumes it in long term, you are between a rock and a hard place. You must either reduce the producer's rate of production, speed up the consumer's rate of consumption, or reduce the overheads in the pipeline to the same effect. Nothing else works.
If rate mismatch is only temporary, you can "paper over the cracks" by adding some extra buffering to the pipeline. If the connection between has some buffering capability, you may be able to increase it. Alternatively, you could add extra buffering at the producer or consumer end.
Here are some things that might help in your particular case.
Reduce the amount of stuff you are writing in the producer threads.
Do less work in the consumer threads, or profile / tune them to do the work faster.
Don't use a socket to communicate between two threads in the same JVM. If you can arrange it, use a Java PipeInputStream / PipeOutputStream pair, or roll your own equivalent. (If you use a socket, reading and writing involves system calls, copying data into and out of kernel buffers and so on.)
In the case where communications has to go outside of the JVM, make sure that you use
Buffered*
wrappers for the underlying streams to reduce the number of syscalls made while reading / writing.