今天沒事干的時候,無意間點到了一個System.out.println()中的println()方法,一個閃亮的關(guān)鍵字沖擊著我的眼睛。
不知道大家知不知道,那就是加鎖的synchronized。但凡有鎖的地方肯定會性能是有損耗的,當(dāng)然得在并發(fā)的情況下!
synchronized在JDK8還是6之后進(jìn)入了鎖升級概念:無鎖--->偏向鎖--->自旋鎖--->輕量級鎖--->重量級鎖
「輕量級鎖和偏向鎖通常不涉及內(nèi)核態(tài)切換」
「在到重量級鎖時涉及到用戶態(tài)和內(nèi)核態(tài)的切換,很影響性能的!」
有興趣的可以自己研究一下synchronized的鎖升級和降級!
下面我們回歸正題,看一下這個System.out.println()!
網(wǎng)上文章很多,大家想看System和out的詳細(xì)解讀,可以去看看哈,這里主要看一下println()這個方法的源碼!
public void println(Object x) { String s = String.valueOf(x); synchronized (this) { print(s); newLine(); }}
我們以傳進(jìn)來的是Object對象為例,其他類型比這個少了一個轉(zhuǎn)化為String在輸出!
這種方式通常被稱為對象級別的鎖,因為它是以對象為粒度進(jìn)行同步的!
print(s);newLine();這兩個操作在同一時間只被一個線程執(zhí)行,以防止輸出的內(nèi)容被多個線程交織在一起,導(dǎo)致輸出混亂。
這種同步是為了保證輸出的可見性和一致性。當(dāng)然也帶來了性能的損耗,一般情況不會引起線程阻塞,當(dāng)多個線程嘗試同時訪問同一個控制臺輸出時,由于控制臺輸出的同步性質(zhì),可能會導(dǎo)致線程競爭鎖,從而導(dǎo)致程序響應(yīng)慢!
當(dāng)然在沒有并發(fā)的場景中,使用一下也沒什么,切記不要在輸出里面加上大量的運算和轉(zhuǎn)換邏輯。
「但是為了不給后期埋雷,咱們還是盡量不要使用。」
「可以使用專門的日志框架,如Log4j、Logback等,它們提供了更靈活的日志記錄和輸出控制。」
我們在查看一下:newLine()
我們會發(fā)現(xiàn)它也是一個加鎖的方法!
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; }}
里面的textOut.flushBuffer()也是有鎖的!
void flushBuffer() throws IOException { synchronized (lock) { ensureOpen(); if (nextChar == 0) return; out.write(cb, 0, nextChar); nextChar = 0; }}
我們在看一下ensureOpen()方法,然后一直點就會發(fā)現(xiàn) write(String chars, int start, int count)也是加著鎖的!
所以我們還是不要輕易在項目中使用哈,「咱們還是使用日志框架」,還能有不用的日志級別打印,多香!
每天一個小技巧哈!
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); }}
使用 System.out.println() 輸出信息到控制臺通常比內(nèi)存操作和計算操作慢得多。這是因為控制臺輸出涉及到文件I/O操作,需要將數(shù)據(jù)寫入控制臺。在高性能的應(yīng)用程序中,頻繁的輸出會導(dǎo)致程序的性能下降,特別是在大規(guī)模數(shù)據(jù)處理和高并發(fā)情況下。
System.out.println() 不支持不同的日志級別(如DEBUG、INFO、ERROR等),因此無法將輸出信息分類為不同的重要性。在生產(chǎn)環(huán)境中,通常需要能夠根據(jù)日志級別過濾和記錄信息。
System.out.println() 輸出的信息通常散落在代碼的各個地方,不容易集中管理。在實際應(yīng)用中,通常需要將日志集中存儲和管理,以便日后的監(jiān)控、分析和故障排查。
我們上面也是說了,這里在強調(diào)一遍哈:
建議使用專門的日志框架來管理和控制日志輸出,一些流行的 Java 日志框架包括:Log4j、Logback、SLF4J
...
雖然 System.out.println() 在快速測試和學(xué)習(xí)階段很有用,但在實際的應(yīng)用程序中,頻繁使用它可能會導(dǎo)致一系列問題。
因此,建議在生產(chǎn)環(huán)境中使用專門的日志框架來管理和控制日志輸出,以便更好地滿足應(yīng)用程序的需求,并提高代碼的可維護(hù)性和可擴(kuò)展性。
本文鏈接:http://www.tebozhan.com/showinfo-26-12711-0.html再使用System.out.println()打印收拾東西回家
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: 我們一起聊聊C#堆排序算法
下一篇: 使用 ClickHouse 做日志分析