Если вы используете консоль Eclipse, на работе, похоже, работают два разных явления: один, как описано в @Gemtastic , является обработкой потоков JVM, а другой - способом Eclipse читает эти потоки, как упоминалось @DraganBozanovic . Поскольку я использую Eclipse, элегантный flush()
-решение, отправленное @BillK , которое касается только проблемы с JVM, недостаточно.
В итоге я написал вспомогательный класс, называемый EclipseTools
со следующим содержимым (и требуемым объявлением пакета и импортом). Это немного взломать, но исправляет обе проблемы:
public class EclipseTools {
private static List streams = null;
private static OutputStream lastStream = null;
private static class FixedStream extends OutputStream {
private final OutputStream target;
public FixedStream(OutputStream originalStream) {
target = originalStream;
streams.add(this);
}
@Override
public void write(int b) throws IOException {
if (lastStream!=this) swap();
target.write(b);
}
@Override
public void write(byte[] b) throws IOException {
if (lastStream!=this) swap();
target.write(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
if (lastStream!=this) swap();
target.write(b, off, len);
}
private void swap() throws IOException {
if (lastStream!=null) {
lastStream.flush();
try { Thread.sleep(200); } catch (InterruptedException e) {}
}
lastStream = this;
}
@Override public void close() throws IOException { target.close(); }
@Override public void flush() throws IOException { target.flush(); }
}
/**
* Inserts a 200ms delay into the System.err or System.out OutputStreams
* every time the output switches from one to the other. This prevents
* the Eclipse console from showing the output of the two streams out of
* order. This function only needs to be called once.
*/
public static void fixConsole() {
if (streams!=null) return;
streams = new ArrayList();
System.setErr(new PrintStream(new FixedStream(System.err)));
System.setOut(new PrintStream(new FixedStream(System.out)));
}
}
Чтобы использовать, просто вызовите EclipseTools.fixConsole()
один раз в начале вашего кода.
В основном это заменяет два потоки System.err
и System.out
с настраиваемым набором потоков, которые просто пересылают свои данные в исходные потоки, но отслеживают, какой поток был записан последним. Если поток, который записывается для изменений, например, System.err.something(...)
, за которым следует System.out.something(...)
, он очищает вывод последнего потока и ждет 200 мс, чтобы дать время консоли Eclipse завершить его печать.
Примечание: 200 мс - это просто приблизительное начальное значение. Если этот код уменьшает, но не устраняет проблему для вас, увеличьте задержку в Thread.sleep
от 200 до чего-то большего, пока она не будет работать. В качестве альтернативы, если эта задержка работает, но влияет на производительность вашего кода (если вы чередуете потоки часто), вы можете попытаться уменьшить его постепенно, пока не начнете получать ошибки.