我們都知道,互聯(lián)網(wǎng)的世界其實就是數(shù)據(jù)的世界,無論你是在微信上聊天,在玩王者榮耀,還是逛淘寶,看小姐姐直播,背后其實都是數(shù)據(jù)的傳輸。

相信大部分學(xué)過計算機操作系統(tǒng)的程序員都知道,假如我們的數(shù)據(jù)存放在計算機的文件上(數(shù)據(jù)庫實際上也是存放在文件上),要把文件上的內(nèi)容拷貝給用戶,需要經(jīng)過多少次復(fù)制呢?
首先,我們需要把內(nèi)容從文件中拷貝到我們的應(yīng)用中,雖然這聽起來只有一次拷貝,實際上操作系統(tǒng)會進行兩次拷貝,首先會先把文件拷貝到操作系統(tǒng)內(nèi)核,然后再從操作系統(tǒng)內(nèi)核上拷貝到應(yīng)用當(dāng)中。同理,我們把內(nèi)容拷貝到Socket傳輸給用戶的過程也是一樣的,需要先拷貝給操作系統(tǒng)內(nèi)核,再拷貝給對應(yīng)的Socket。一個簡單的功能,竟然要經(jīng)過4次拷貝。
那么如何優(yōu)化這么一個過程呢?linux有一個非常牛的技術(shù),叫做零拷貝,那么在JAVA中如何實現(xiàn)呢?我發(fā)現(xiàn)很多Java程序員,雖然說是精通Java更多的是精通JavaWeb。其實Java也是非常博大精深的,Java的NIO其實已經(jīng)幫我們解決了這個問題。
在Java NIO中,我們可以通過FileChannel.map,可以越過內(nèi)核態(tài),直接從文件拷貝數(shù)據(jù)到應(yīng)用當(dāng)中,同樣,可以把越過內(nèi)核態(tài),直接把數(shù)據(jù)從應(yīng)用中拷貝到Socket中發(fā)送給用戶。這樣子,我們的系統(tǒng)調(diào)用,就變成了文件到應(yīng)用到Socket,只要進行2次拷貝即可。
同時,我們Java NIO還提供給我們另外一個方法,可以不用經(jīng)過應(yīng)用,直接從文件中拷貝到Socket中,這就是FileChannel.transferTo。它會把數(shù)據(jù)從文件拷貝到內(nèi)核中,然后從內(nèi)核直接把數(shù)據(jù)再次拷貝給接收的Socket發(fā)送給用戶。
總結(jié)
好了,這就是Java當(dāng)中的零拷貝技術(shù)了。JavaNIO,在程序員面試中也是經(jīng)常出現(xiàn)的,如果你有興趣,歡迎關(guān)注我,我們一起學(xué)習(xí),共同進步。同名公眾號(沙茶敏碎碎念)