System.out.println()标准输出方法性能影响一窥
来源:互联网 发布:php全站搜索 编辑:程序博客网 时间:2024/06/07 09:14
System.out.println()标准输出方法性能影响一窥
#
以前在写功能性代码的时候就知道,代码功能性的强大往往意味着性能的丢失。
那么非常好用支持任何格式输出到控制台的System.out.println()标准输出方法究竟是如何工作的呢?
做一个简单的测试
public class TestOut { private static long timeOut = System.currentTimeMillis() + 1000L; private static void outQuick() { long i = 1L; while (timeOut >= System.currentTimeMillis()) { i++; } System.out.println(i); } private static void outOnlyNumber() { long i = 1L; while (timeOut >= System.currentTimeMillis()) { System.out.println(i++); } } private static void outOnlyString() { long i = 1L; while (timeOut >= System.currentTimeMillis()) { System.out.println(""+i++); } } public static void main(String[] args) { outQuick(); //outOnlyNumber(); //outOnlyString(); }}
首先测试的没有使用标准输出方法的运算,得到的结果稳定在2亿4千万次到2亿七千万次左右,下面给出几次结果
256908210241685465271216750259256219
第二次测试的打印数字,执行结果大概在17万到25万之间,其中大多数为17万左右
170775160830175684251080
第三次测试打印把数字转成字符然后再输出,执行结果稳定在20万以上
276857252494230742291023
得到以下几条信息
- System.out.println()标准输出方法对性能的影响导致执行效率下降了1500倍左右
- System.out.println()标准输出方法使用字符串输出时执行效率只下降1000倍左右
为什么会这样呢?
看看源码,发现System.out.println()标准输出方法的执行过程是这样的
/** * 参数不同会调用不同的构造方法 * Prints a String and then terminate the line. This method behaves as * though it invokes <code>{@link #print(String)}</code> and then * <code>{@link #println()}</code>. * * @param x The <code>String</code> to be printed. */ public void println(String x) { synchronized (this) { print(x); newLine(); } }/** * 如果是一个对象,则会多一句代码String s = String.valueOf(x); * Prints an Object and then terminate the line. This method calls * at first String.valueOf(x) to get the printed object's string value, * then behaves as * though it invokes <code>{@link #print(String)}</code> and then * <code>{@link #println()}</code>. * * @param x The <code>Object</code> to be printed. */ public void println(Object x) { String s = String.valueOf(x); // 该方法是一个synchronized的方法,首先打印字符,然后换一行。 synchronized (this) { print(s); // newLine()也是一个synchronized的方法 newLine(); } }/** * 多出的这一句代码实质上是调用了对象的toString()方法并做了空判断 * Returns the string representation of the {@code Object} argument. * * @param obj an {@code Object}. * @return if the argument is {@code null}, then a string equal to * {@code "null"}; otherwise, the value of * {@code obj.toString()} is returned. * @see java.lang.Object#toString() */ public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); }/** * 也许你以为newLine()方法只是打印一个\n,但是实际上,他却是这样的 * 其中textOut.flushBuffer();也是一个synchronized方法 * 如果在这个过程中发生了IO中断异常,newLine()方法会中断掉当前线程 */private void newLine() { try { synchronized (this) { ensureOpen(); textOut.newLine(); textOut.flushBuffer(); charOut.flushBuffer(); if (autoFlush) out.flush(); } } catch (InterruptedIOException x) { Thread.currentThread().interrupt(); } catch (IOException x) { trouble = true; } }/** * 将输出缓冲区刷新到基础字符流 * Flushes the output buffer to the underlying character stream, without * flushing the stream itself. This method is non-private only so that it * may be invoked by PrintStream. */ void flushBuffer() throws IOException { synchronized (lock) { ensureOpen(); if (nextChar == 0) return; out.write(cb, 0, nextChar); nextChar = 0; } }/** * 打印字符,如果字符不为空的话 * Prints a string. If the argument is <code>null</code> then the string * <code>"null"</code> is printed. Otherwise, the string's characters are * converted into bytes according to the platform's default character * encoding, and these bytes are written in exactly the manner of the * <code>{@link #write(int)}</code> method. * * @param s The <code>String</code> to be printed */ public void print(String s) { if (s == null) { s = "null"; } write(s); }/** * 输出字符的write方法和newLine动作其实是一致的 * System.out.println()标准输出方法其实相当于print()方法调用两次 */private void write(String s) { try { synchronized (this) { ensureOpen(); // textOut是BufferedWriter的一个对象,该类继承至Object以及Writer类 // 该类是一个抽象类,作用是向字符流中执行写入。 textOut.write(s); textOut.flushBuffer(); charOut.flushBuffer(); if (autoFlush && (s.indexOf('\n') >= 0)) out.flush(); } } catch (InterruptedIOException x) { Thread.currentThread().interrupt(); } catch (IOException x) { trouble = true; } }/** * textOut.write(s);调用的是该方法 * 但是该方法只是把字符拆分一些信息来传递参数 * Writes a string. * * @param str * String to be written * * @throws IOException * If an I/O error occurs */ public void write(String str) throws IOException { write(str, 0, str.length()); }/** * 该方法也是synchronized的 * lock其实是this,通过this.lock=this获得 * Writes a portion of a string. * * @param str * A String * * @param off * Offset from which to start writing characters * * @param len * Number of characters to write * * @throws IndexOutOfBoundsException * If <tt>off</tt> is negative, or <tt>len</tt> is negative, * or <tt>off+len</tt> is negative or greater than the length * of the given string * * @throws IOException * If an I/O error occurs */ public void write(String str, int off, int len) throws IOException { synchronized (lock) { char cbuf[]; if (len <= WRITE_BUFFER_SIZE) { if (writeBuffer == null) { writeBuffer = new char[WRITE_BUFFER_SIZE]; } cbuf = writeBuffer; } else { // Don't permanently allocate very large buffers. cbuf = new char[len]; } str.getChars(off, (off + len), cbuf, 0); write(cbuf, 0, len); } }
阅读全文
2 0
- System.out.println()标准输出方法性能影响一窥
- 关于java项目中System.out.println()标准输出方法性能影响分析
- System.out.println()方法
- 快速输出System.out.println()
- 安卓System.out.println控制台输出方法
- 安卓System.out.println控制台输出方法
- System.out.println 的输出顺序..
- System.out.println()输出到文件里
- System.out.println() 输出中文乱码
- System.out.println()输出到文件
- android System.out.println无输出
- hadoop中查看System.out.println输出
- android设置输出System.out.println
- logcat监听System.out.println()的输出
- 更改System.out.println()的输出路径
- 系统性能提升----System.out.println()
- 问题 System.out.println(versionName);输出结果:System.out: INSTANT_RUN
- System.out.println方法的使用
- HTTPS 原理解析
- Spring AOP
- python 安装matplotlib后运行图表时提示错误numpy版本不对的解决方法
- 金字塔
- C++参数传递过程
- System.out.println()标准输出方法性能影响一窥
- js的co.js源码解析
- vuejs入门(1)
- 写时拷贝
- linux命令学习笔记一
- C#调用BarTender 模板
- DatePickerDialog和TimePickerDialog的运用
- VC++ 使用预编译头
- 二分查找