gpt4 book ai didi

java - 线程一直卡在 Socket/Printwriter 交互上

转载 作者:行者123 更新时间:2023-11-30 11:35:51 25 4
gpt4 key购买 nike

我的程序运行了一段时间(大约 20 秒),然后它发送的消息越来越少,直到停止。我做了一个线程转储,它指向线程停止的以下代码行:

if(s.isClosed() || !s.isConnected() || s.isInputShutdown() || s.isOutputShutdown() || out == null || out.checkError()) {

这是我线程转储的一部分

    "class xxx.xxx.xxx" prio=10 tid=0x000000000200d800 nid=0x6e7f waiting for monitor entry [0x00007f63172b6000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.io.PrintWriter.flush(PrintWriter.java:291)
- waiting to lock <0x00000000ec810218> (a java.io.BufferedWriter)
at java.io.PrintWriter.checkError(PrintWriter.java:330)

此线程转储信息指出问题出在 Printwriter.checkError() 中。但我不明白为什么它会停在这里。

下面是上下文中的代码。 (接收者是一个 Map<Socket, PrintWriter> )

public void parseMessage(final byte[] bytes) {
synchronized (receivers) {
for (final Socket s : receivers.keySet()) {
final PrintWriter out = receivers.get(s);
if(s.isClosed() || !s.isConnected() || s.isInputShutdown() || s.isOutputShutdown() || out == null || out.checkError()) {
receivers.remove(s);
failedToConnect(s.getInetAddress().getHostAddress(), s.getPort());
continue;
}
queue.add(out, bytes);
}
}
}

1 月 14 日(10:00 GMT+1)更新:

替换了 PrintWriterBufferedWriter

1 月 14 日 (16:00 GMT+1) 更新:

我又进行了一些测试,结果证明是某些网络/阅读器之间的某种通信问题导致了麻烦。该应用程序正在向其内部网络中的某些阅读器发送数据,并向某些外部网络(通过互联网)中的某些阅读器发送数据。究竟是什么原因导致这一点仍然未知,但有一些线索。重新启动几次后,我可以看到两个网络之间的连接未关闭,因此连接保持打开状态。我仍然不知道这里到底发生了什么,但在我看来这是某种网络问题。在服务器端,连接保持在“FIN_WAIT1”,在阅读器端保持“ESTABLISHED”。看起来阅读器不会发出关闭连接的信号,即使已发送关闭连接的信号也是如此。

最佳答案

if(s.isClosed() || !s.isConnected() || s.isInputShutdown() || s.isOutputShutdown() || out == null || out.checkError())

这是一系列几乎无用的测试。

  • 如果套接字已关闭,您根本不应该在这部分代码中。
  • 如果套接字未连接,同上。
  • 如果您关闭了用于输入的套接字,并不意味着您不能写入。
  • 如果您关闭了用于输出的套接字,则您不应出现在这部分代码中。
  • 如果 out 为 null,则您不应出现在这部分代码中。
  • 测试 checkError() 很好,但您根本不应该在网络上使用 PrintWriter,因为它会吞噬异常。最好使用 BufferedWriter 并让异常告诉您发生错误的情况,而不是像您在这里所做的那样在下一次写入时告诉您。

您还需要了解,Socket.isClosed() 仅告诉您 是否已关闭Socket。 同样, Socket.isConnected() 仅告诉您已连接 Socket, 或已通过构造函数或 ServerSocket.accept() 接收到它。 isInputShutdown()isOutputShutdown() 也是如此。它们只会告诉您对 Socket 做了什么。 这些方法都不会告诉您关于连接 状态的任何信息。

This thread dump info points out that the problem lies in Printwriter.checkError(). But i can't understand why it would stop here.

因为,正如堆栈跟踪还告诉您的那样,它正在调用 flush()。 如果阻塞,则意味着您已经超出读取器的范围,并且 TCP 正在等待他读取一些数据以释放他的套接字接收缓冲区中的缓冲区空间以及您的套接字发送缓冲区中的缓冲区空间。在此之前,底层的 send() 将被阻塞。您对此无能为力,只能加快阅读速度。

关于java - 线程一直卡在 Socket/Printwriter 交互上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14860277/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com