2012-02-27 4 views
4

У меня есть многопоточное Java-приложение, которое будет выводить информацию о полученном им сообщении на консоль для целей отладки. Каждый раз, когда приложение получает сообщение, оно вызывает сообщение System.out.println(String).Несколько потоков, использующих System.out.println в Java

Проблема, с которой я столкнулся, заключается в том, что если приложение заливается сообщениями, System.out.println() печатает ошибочную информацию (например, информацию старого буфера). Это заставляет меня задаться вопросом, есть ли проблема с потоками, когда несколько потоков одновременно вызывают функцию println, а не правильно очищая буфер.

В моей основной программе (нить), у меня есть что-то эффект:

while(iterator.hasNext()) 
{ 
    SelectionKey key = iterator.next(); 

    channel.receive(buffer);  // The buffer is a ByteBuffer. 
    buffer.flip(); 

    new Thread(new ThreadToPrintTheMessage(buffer)).start(); 

    buffer.clear(); 

    iterator.remove(); 
} 

В моей теме, у меня есть что-то эффект:

@Override 
public void run() 
{ 
    System.out.println(message); 
    System.out.flush(); // I have better results with this. But, it doesn't 
          // fully resolve the issue. 
} 

Есть ли простой Кстати, для меня есть возможность одновременного вывода нескольких потоков на консоль без буферов, содержащих старую информацию?

Благодаря

EDIT: обновленный код в основном потоке, чтобы быть более представительным, что делает моя программа.

+2

Можете ли вы показать часть «старой информации о буфере». 'System.out.println' синхронизируется, поэтому вы не должны получать« старую »информацию. – Gray

+0

несколько потоков выходят на консоль за один раз? вы имеете в виду каждую нить за раз? – kosa

+0

Например, если я получаю XML-сообщения, у вас будет что-то вроде:>/tag> – Phanto

ответ

2

Здесь может быть какой-то пример кода, чтобы решить эту проблему:

while(iterator.hasNext()) 
{ 
    SelectionKey key = iterator.next(); 

    channel.receive(buffer);  // The buffer is a ByteBuffer. 
    buffer.flip(); 
    byte[] bytes = new byte[buffer.limit()]; // copy buffer contents to an array 
    buffer.get(bytes); 
    // thread will convert byte array to String 
    new Thread(new ThreadToPrintTheMessage(bytes)).start(); 

    buffer.clear(); 

    iterator.remove(); 
} 
+0

Я попробую. – Phanto

+0

Так оно и было! Вы и Александр Павлов определили, в чем проблема ... Я пытался распечатать буфер, который был разделен и изменен другим ресурсом. – Phanto

2
synchronized (System.out) { 
    System.out.println(message); 
    System.out.flush(); 
} 
+3

'System.out.println()' уже синхронизирован. – Gray

+0

@Gray прав, просто подумал, что это могла быть гонка между 'println()' и 'flush()', но, очевидно, это не так. @Phanto, какой выход вы получаете? –

+0

@ АлександрПавлов, пожалуйста, см. Комментарий в главном посте. – Phanto

1

Вы должны использовать java.util.logging или какую-либо другую среду журналирования для этой цели.

http://docs.oracle.com/javase/1.4.2/docs/api/java/util/logging/Logger.html

import java.util.logging.Logger; 
.... 
Logger log = Logger.getLogger("com.something.something"); 
.... 
log.log(Level.Info, "Message"); 
+0

Не могли бы вы привести небольшой пример? – Phanto

+1

добавлен очень простой пример –

2

Я не получил время, чтобы проверить Println источник будет убедиться, что это поточно всегда (вы могли бы , если вы хотите), но уверены ли вы, что ваш println ошибается? Вполне возможно, что код работает в совсем другое время, чем вы думаете. Темы часто зацикливаются на замках или просто забываются планировщиком, поэтому то, что вы думаете, должно запускать A, B, C, D, может запускать B, C, D, A. Тогда вы задаетесь вопросом, почему println испорчен, печать последнего, что вы думаю побежал первым. И это действительно простой пример. Разница между тем, что вы ожидаете от многопоточности и того, что происходит, может быть поистине поразительной. Как правило, чем выше отношение потоков к ядру, тем хуже. Одноядерные машины всегда делают все наоборот, чего вы ожидаете.

И для этого вам даже не требуется несколько потоков. Мои первые толчки появились с очередями событий (в Windows 3.1), которые не разделяли мои взгляды на то, когда все должно работать. Мне потребовалось некоторое время, чтобы понять, что сообщения были скремблированы, потому что у ОС было совсем другое представление о том, как они должны работать, чем я.

Возможно, некоторые тонкости с System.out.println и флешем, о которых я не знаю, но даже когда вы получаете все, что работает, имейте в виду, что эти потоки имеют скорее противоположные умы. Даже Logger не решит все ваши проблемы.

+0

По словам нескольких людей, println является потокобезопасным, поэтому он действительно может быть запутанным расписанием. – malexmave

Смежные вопросы