Java Log4j正在挂起我的应用程序我做错了什么?

Java Log4j正在挂起我的应用程序我做错了什么?,java,multithreading,log4j,deadlock,Java,Multithreading,Log4j,Deadlock,首先介绍一下应用程序的背景知识。我有一个通过线程池并行处理许多独立任务的应用程序。线程池现在已挂起 下面是我的线程转储的一个片段,池2中的所有线程都被“pool-2-thread-78”阻塞。它似乎被锁定,试图写入控制台,我觉得非常奇怪。有人能帮我解释一下情况吗 编辑: 站台详情 java版本“1.6.0_07” Java(TM)SE运行时环境(build 1.6.0_07-b06) Java热点(TM)客户端虚拟机(构建10.0-b23,混合模式,共享) Ubuntu Linux服务器双四核机

首先介绍一下应用程序的背景知识。我有一个通过线程池并行处理许多独立任务的应用程序。线程池现在已挂起

下面是我的线程转储的一个片段,池2中的所有线程都被“pool-2-thread-78”阻塞。它似乎被锁定,试图写入控制台,我觉得非常奇怪。有人能帮我解释一下情况吗

编辑: 站台详情 java版本“1.6.0_07” Java(TM)SE运行时环境(build 1.6.0_07-b06) Java热点(TM)客户端虚拟机(构建10.0-b23,混合模式,共享)

Ubuntu Linux服务器双四核机器

在写入printstream时,它似乎被锁定,我考虑过只删除控制台appender,但是我更希望知道它为什么会被阻塞,并根据这些知识删除它。在过去,移除并查看其是否有效的方法又回来咬我:)

我的log4j中的相关部分

log4j.rootLogger=DEBUG,STDOUT log4j.logger.com.blah=INFO,LOG log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender log4j.appender.LOG=org.apache.log4j.FileAppender

线程转储提取

“pool-2-thread-79”Id=149阻塞在 org.apache.log4j.spi。RootLogger@6c3ba437 由“池-2-线程-78”拥有,Id=148 at org.apache.log4j.Category.callAppenders(Category.java:201) 在 org.apache.log4j.Category.forcedLog(Category.java:388) 在 org.apache.log4j.Category.error(Category.java:302) 在 运行(MessageProcessTask.java:103) 在 Executors$RunnableAdapter.call(Executors.java:441) 在 java.util.concurrent.FutureTask$Sync.innerRun(FutureTask/java:268) 在 java.util.concurrent.FutureTask.run(FutureTask/java:54) 在 java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907) 在 run(Thread.java:619)

“池-2-线程-78”Id=148可在 java.io.FileOutputStream.writeBytes(本机) 方法)在 write(FileOutputStream.java:260) 在 java.io.BufferedOutputStream.write(BufferedOutputStream.java:105) -锁定(java.io.BufferedOutputStream)在 java.io.PrintStream.write(PrintStream.java:430) -锁定(一个java.io.PrintStream)在 org.apache.log4j.ConsoleAppender$SystemOutStream.write(ConsoleAppender.java:173) 在 sun.nio.cs.streamncoder.writeBytes(streamncoder.java:202) 在 sun.nio.cs.streamncoder.implFlushBuffer(streamncoder.java:272) 在 sun.nio.cs.streamncoder.implFlush(streamncoder.java:276) 在 flush(StreamEncoder.java:122) -锁定(java.io.OutputStreamWriter)在 java.io.OutputStreamWriter.flush(OutputStreamWriter.java:212) 在 org.apache.log4j.helpers.QuietWriter.flush(QuietWriter.java:57) 在 org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:315) 在 org.apache.log4j.WriterAppender.append(WriterAppender.java:159) 在 org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:230) -锁定(org.apache.log4j.ConsoleAppender)在 appenderatachableimpl.appenderlooponappenders(appenderatachableimpl.java:65) 在 org.apache.log4j.Category.callAppenders(Category.java:203) -锁定(org.apache.log4j.spi.RootLogger)在 org.apache.log4j.Category.forcedLog(Category.java:388) 在 org.apache.log4j.Category.error(Category.java:302) 在 运行(MessageProcessTask.java:103) 在 Executors$RunnableAdapter.call(Executors.java:441) 在 java.util.concurrent.FutureTask$Sync.innerRun(FutureTask/java:268) 在 java.util.concurrent.FutureTask.run(FutureTask/java:54) 在 java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907) 在 run(Thread.java:619)


首先,我相信log4j会连续写入文件和控制台,否则所有日志都会被破坏。因此,当一个线程正在写入另一个想要写入的线程时,必须等待另一个线程完成。另外,如果在另一端连接到标准输出的任何东西没有排出,标准输出可能会阻塞


在unix中有一个特殊的文件描述符,称为标准输出。在控制台中启动应用程序时,标准输出将连接到控制台。您还可以将标准输出重定向到其他文件。例如:javablah>/dev/null。很可能您的标准输出指向正在填充的文件。例如,管道是一个文件,如果另一端的程序没有排空管道,则写入管道的程序最终将阻塞。

您可以使用AsyncAppender更好地将记录器与Appender分离

在Windows上,如果您在控制台窗口中单击,这将暂停控制台,例如,标准输出缓冲区将填满,并且当控制台附加程序连续写入时,您的应用程序将挂起,直到您释放控制台(按enter或其他键)


考虑将AsyncAppender与log4j一起使用-大多数情况下这是个好主意-唯一的问题是-Asynapender缓冲区在退出时没有完全刷新。

您可以发布有关您的环境的更多信息吗?我在windows下看到过这种情况,在试图查看日志记录的同时在cmd shell中运行。感谢carson,我在问题+1中添加了更多细节,以“…基于此知识删除它…”我在类似的linux硬件上看到了相同的死锁;在我的例子中,java进程是通过ssh在远程服务器上启动的。当进程死锁时,大约有140万条日志被写入;具有相似日志数量的其他相同进程以相同方式在其他相同硬件上启动,继续正常处理。Se