我正在使用java编写程序,我使用一些错误打印语句进行调试。 我的程序生成大约2000个线程。程序运行正常,直到大量线程访问此语句:
System.err.println("Some error message");
当发生这种情况时,我的一个线程成功地设法访问println函数,而其他线程具有状态:
JVM中的状态:等待同步块
深入研究调试语句我注意到设法访问println函数的线程在此函数处停止:
private native void writeBytes(byte b[], int off, int len , boolean append) throws IOException;
它有以下堆栈跟踪:
java.io.FileOutputStream.write(FileOutputStream.java:327)
java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
java.io.PrintStream.write(PrintStream.java:482)
sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
java.io.PrintStream.write(PrintStream.java:527)
java.io.PrintStream.print(PrintStream.java:669)
java.io.PrintStream.println(PrintStream.java:806)
fetcher.responseHandler.ExtendedResponseHandler500.handleResponse(ExtendedResponseHandler500.java:20)
fetcher.FetchWorker.run(FetchWorker.java:79)
java.lang.Thread.run(Thread.java:745)
当其他线程在println函数的第一行停止时(在java核心代码中):
synchronized(this)
这个问题是由我引起的吗?或者此错误与JVM有关吗?我能解决这个问题吗?
答案 0 :(得分:2)
最可能的原因是进程的输出流未被父进程占用,因此stdout缓冲区填满,然后对System.err.println的下一次调用将永远挂起。
当一个进程用于启动另一个进程时,这很常见,但是没有设置“刷新”线程来排空子进程的stdout和stderr流。
请注意,这与“线程”没有任何关系 - 但是启动多个线程肯定会增加生成错误的速率(如果由于下游争用而导致其他错误,可能会导致更多的总错误)这意味着您的输出缓冲区填满得更快并且更早挂起。
答案 1 :(得分:-1)
2000个线程等待获取println调用的锁定是完全正常的。
您的堆栈跟踪显示您收到一些HTTP 500错误。可能大多数你的线程都遇到了这个错误,现在全部都在报告标准错误。你所看到的是你的问题的结果,而不是原因。
2000线程是一个疯狂的数字,它不会改善任何合理情况下的性能,并且很可能会降低性能。从类似于4的东西开始,看看是否逐渐加倍该值会给你带来任何改进。 JVM可以处理这么多线程(所以这不是你的问题的根源),但它只是没用。使用更多JVM无法解决问题(可能是简单的HTTP 500和/或网络超时)。 另请检查服务器端日志。
如果你需要最大化性能(在真正的高并发场景中)考虑asynchio,但正常IO对于所有常见情况都非常好,并且在这里似乎很好。
<强>更新强> 我的想法是:
步骤3可能需要花费很多时间,所以即使采用多个线程转储,您也会看到始终出现的相同线程(我的意思是您需要非常幸运地在步骤1中看到Thread-1352或2)。我假设您检查了线程名称,并且我们正在讨论的锁定线程始终是相同的。 你看到程序&#34;冻结&#34; (它冻结了,对吗?)或者一切都还在吗?你花了多少线程转储,中间有多少时间?