Log4j висит мое приложение, что я делаю неправильно? - программирование

Log4j висит мое приложение, что я делаю неправильно?

Сначала расскажем о приложении. У меня есть приложение, обрабатывающее множество независимых задач параллельно через пул потоков. Пул потоков теперь висит.

Ниже приведен фрагмент из моих дампов потоков, все мои потоки в пуле-2 BLOCKED являются "пул-2-нить-78". Кажется, он заблокирован, пытаясь написать консоль, которую я считаю крайне странным. Может ли кто-нибудь пролить свет на ситуацию для меня?

ИЗМЕНИТЬ: Информация о платформе java-версия "1.6.0_07" Java (TM) SE Runtime Environment (сборка 1.6.0_07-b06) Клиентская виртуальная машина Java HotSpot (TM) (сборка 10.0-b23, смешанный режим, совместное использование)

Сервер двухъядерных процессоров Linux Ubuntu Linux.

Кажется, что он блокируется при записи в printstream, я рассмотрел просто удаление консольного приложения, но я бы лучше знал, почему он блокирует и удаляет его на основе этих знаний. Раньше удалял и смотрел, если он работает, вернулся, чтобы укусить меня:)

соответствующий раздел из моего 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 BLOCKED on [email protected] принадлежащий "pool-2-thread-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)   в com.blah.MessageProcessTask.run(MessageProcessTask.java:103)   в java.util.concurrent.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)   в java.lang.Thread.run(Thread.java:619)

"pool-2-thread-78" Id = 148 RUNNABLE at java.io.FileOutputStream.writeBytes(Native Метод) при java.io.FileOutputStream.write(FileOutputStream.java:260)   в java.io.BufferedOutputStream.write(BufferedOutputStream.java:105)   - заблокирован < 0x6f314ba4 > (java.io.BufferedOutputStream) в java.io.PrintStream.write(PrintStream.java:430)   - заблокировано < 0xd5d3504 > (java.io.PrintStream) в org.apache.log4j.ConsoleAppender $SystemOutStream.write(ConsoleAppender.java:173)   в sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:202)   в sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:272)   в sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:276)   в sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:122)   - заблокирован < 0x6243a076 > (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)   - заблокировано < 0x45dbd560 > (org.apache.log4j.ConsoleAppender) в org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:65)   в org.apache.log4j.Category.callAppenders(Category.java:203)   - заблокировано < 0x6c3ba437 > (a org.apache.log4j.spi.RootLogger) в org.apache.log4j.Category.forcedLog(Category.java:388)   в org.apache.log4j.Category.error(Category.java:302)   в com.blah.MessageProcessTask.run(MessageProcessTask.java:103)   в java.util.concurrent.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)   в java.lang.Thread.run(Thread.java:619)

4b9b3361

Ответ 1

Вы можете использовать AsyncAppender, чтобы лучше отсоединить регистратор от добавлений.

В Windows, если вы нажмете в окне консоли, это приостановит консоль, например. буфера stdout будет заполняться, и по мере того, как консольный appender будет записывать последовательно, ваше приложение будет зависать, пока вы не отпустите консоль (нажмите клавишу ввода или так).

Рассмотрите возможность использования AsyncAppender с log4j - в большинстве случаев это хорошая идея - единственная проблема, связанная с тем, что буфер AsynAppender не полностью очищается при выходе.

Ответ 2

во-первых, я считаю, что log4j записывается в файлы и консоль поочередно, иначе все ваши журналы будут повреждены. поэтому, пока один поток пишет другой поток, который хочет писать, должен ждать, пока другой не будет завершен. Кроме того, stdout может блокировать, если все, что прикреплено к нему на другом конце, не истощает его.

в unix есть специальный файловый дескриптор, называемый stdout. когда вы запускаете приложения на консоли, stdout будет прикрепляться к консоли. вы также можете перенаправить stdout в другие файлы. ex: java Blah > /dev/null. Скорее всего, у вас есть stdout, указывающий на файл, который заполняется. например, труба является файлом, и если программа на другом конце не дренирует трубку, тогда программа, которая записывает в трубу, в конечном итоге блокируется.