我正在用Java编写一个模拟重力的程序,在程序中有很多日志语句(使用System.out输出)。我的程序运行速度非常慢,我认为日志记录可能是其中的原因之一。是否有办法禁用System.out,使得我的程序不会在打印日志时变慢?或者我必须手动去逐个注释调试语句来启用/禁用它们?
我正在用Java编写一个模拟重力的程序,在程序中有很多日志语句(使用System.out输出)。我的程序运行速度非常慢,我认为日志记录可能是其中的原因之一。是否有办法禁用System.out,使得我的程序不会在打印日志时变慢?或者我必须手动去逐个注释调试语句来启用/禁用它们?
可以再次使用输出流吞噬器,类似于以下内容...
System.setOut(new PrintStream(new OutputStream() {
@Override
public void write(int arg0) throws IOException {
}
}));
但更好的解决方案是使用已经提到过的正式日志记录工具。
我同意其他人的看法,应该使用适当的记录器。然而并非每种情况都可以这样做。如下代码禁用了输出,并且像OP要求的那样速度很快:
System.setOut(new java.io.PrintStream(new java.io.OutputStream() {
@Override public void write(int b) {}
}) {
@Override public void flush() {}
@Override public void close() {}
@Override public void write(int b) {}
@Override public void write(byte[] b) {}
@Override public void write(byte[] buf, int off, int len) {}
@Override public void print(boolean b) {}
@Override public void print(char c) {}
@Override public void print(int i) {}
@Override public void print(long l) {}
@Override public void print(float f) {}
@Override public void print(double d) {}
@Override public void print(char[] s) {}
@Override public void print(String s) {}
@Override public void print(Object obj) {}
@Override public void println() {}
@Override public void println(boolean x) {}
@Override public void println(char x) {}
@Override public void println(int x) {}
@Override public void println(long x) {}
@Override public void println(float x) {}
@Override public void println(double x) {}
@Override public void println(char[] x) {}
@Override public void println(String x) {}
@Override public void println(Object x) {}
@Override public java.io.PrintStream printf(String format, Object... args) { return this; }
@Override public java.io.PrintStream printf(java.util.Locale l, String format, Object... args) { return this; }
@Override public java.io.PrintStream format(String format, Object... args) { return this; }
@Override public java.io.PrintStream format(java.util.Locale l, String format, Object... args) { return this; }
@Override public java.io.PrintStream append(CharSequence csq) { return this; }
@Override public java.io.PrintStream append(CharSequence csq, int start, int end) { return this; }
@Override public java.io.PrintStream append(char c) { return this; }
});
我的样本测量结果如下:
OutputStream
中的 write(int)
方法需要 57 毫秒PrintStream
的方法需要 31 毫秒println
和 printf
使用时,只需要 5 毫秒因此,它比其他答案更快,但无法击败不存在的代码(在 System.out
中加上注释或包装在 if (DEBUG)
中),因为可变参数会分配数组和封装基元类型,StringBuilder
(+
也一样)依然会执行。
stdout = System.out
然后调用 System.setOut(stdout)
- TWiStErRobjava.util.logging
)的铁杆粉丝。我建议您在未来了解log4j(或类似的库)。它的工作方式与system.out相同,但实际上有开关可以在需要时关闭它们。
如果您的应用程序是在命令行中启动的,您可以在操作系统级别禁用整个程序的标准输出流。这将有效地禁用所有System.out.prinln(),而无需更改任何代码。
在Linux/Unix上,您可以通过将stdout重定向到/dev/null来关闭它:java MyJavaProgram > /dev/null
如果您不介意只需一次全部完成,您可以创建一个常量来“启用”或“禁用”,并添加一个标志以仅在启用该常量时打印。然后您可以轻松地翻转该常量。
public static boolean PRINTLN_ENABLED = true;
if(Constant.PRINTLN_ENABLED)
System.out.println();
既然你在评论中提到了Eclipse,那么你可以在这里找到相关的答案:https://dev59.com/RUfRa4cB1Zd3GeqP8mEa#799277
(我一开始想把这个作为对shj回答的评论发布,但看起来我需要更多的声望)
最好的长期解决方案是使用一个日志框架。我通常使用内置的日志记录,因为我尽量避免额外的依赖。你可以在这里阅读更多信息:http://docs.oracle.com/javase/1.4.2/docs/guide/util/logging/overview.html
我猜你可以使用System.setOut(PrintStream)
来委托一个什么也不做的PrintStream
,但这可能无法消除所有开销——例如,我猜错误消息的格式化仍然会花费你的时间。
我曾在我的Web项目中的查找监听器中放置了这段代码并解决了问题
/*
* In this case, if you are not in debug mode or any other
*the default system out is replaced internally with this
*implementation, else it works as expected. This way you do not
*have to find and replace anything in your code.
*/
//or as i did servletContext.getInitParameter("mode")
//from web.xml for global parameter
if(!DEBUG) {
System.setOut(
new PrintStream(new OutputStream() {
public void close() {}
public void flush() {}
public void write(byte[] b) {}
public void write(byte[] b, int off, int len) {}
public void write(int b) {}
} );
}
}
System.out
并不是(正如您已经发现的那样)一个记录API;请考虑使用java.util.logging或其他众多替代方案。 - McDowell