摘要:什么是零拷貝我們首先來(lái)認(rèn)識(shí)一下傳統(tǒng)的操作。因?yàn)樵谶@套體系里,不僅僅提供了非阻塞的編程模型,而且提供了類(lèi)似零拷貝,內(nèi)存映射這樣的新技術(shù)對(duì)于操作系統(tǒng)來(lái)說(shuō)早就有了。
什么是零拷貝?
我們首先來(lái)認(rèn)識(shí)一下傳統(tǒng)的I/O操作。
假如說(shuō)用戶進(jìn)程現(xiàn)在要把一個(gè)文件復(fù)制到另一個(gè)地方。
那么用戶程序必須先把這個(gè)文件讀入內(nèi)存,然后再把內(nèi)存里的數(shù)據(jù)寫(xiě)入另一個(gè)文件。
不過(guò)文件讀入內(nèi)存也不是直接讀入用戶進(jìn)程的內(nèi)存,而是先讀入操作系統(tǒng)內(nèi)核的內(nèi)存,然后再?gòu)牟僮飨到y(tǒng)內(nèi)核的內(nèi)存區(qū)讀到用戶進(jìn)程的內(nèi)存。
與之對(duì)應(yīng)的是,寫(xiě)文件也不是直接寫(xiě)到磁盤(pán)上的文件,而是用戶進(jìn)程先把自己內(nèi)存的數(shù)據(jù)傳到操作系統(tǒng)內(nèi)核的內(nèi)存,然后再?gòu)牟僮飨到y(tǒng)內(nèi)核的內(nèi)存區(qū)寫(xiě)到磁盤(pán)。而這其中涉及到諸多的系統(tǒng)調(diào)用。
因此看上去簡(jiǎn)單的操作至少要分為四部
1磁盤(pán)文件讀入操作系統(tǒng)
2操作系統(tǒng)讀到用戶進(jìn)程
3用戶進(jìn)程寫(xiě)到操作系統(tǒng)
4操作系統(tǒng)寫(xiě)入磁盤(pán)文件
零拷貝和傳統(tǒng)I/O有和不同?
零拷貝就是指,傳輸一個(gè)文件的時(shí)候,不需要把文件讀到用戶進(jìn)程再處理,而是直接把文件讀到操作系統(tǒng)一個(gè)內(nèi)存區(qū),然后再移動(dòng)到操作系統(tǒng)的另一個(gè)內(nèi)存區(qū),最后寫(xiě)入文件。
這樣一來(lái),步驟變成這樣:
1磁盤(pán)文件讀入操作系統(tǒng)
2操作系統(tǒng)把數(shù)據(jù)寫(xiě)入操作系統(tǒng)另一個(gè)區(qū)域
3操作系統(tǒng)寫(xiě)入磁盤(pán)文件
雖然只少了一步,但是這里不僅減少了數(shù)據(jù)移動(dòng)的時(shí)間損耗,而且減少了系統(tǒng)調(diào)用的次數(shù),因此大大縮短了時(shí)間。
更加詳細(xì)的解釋請(qǐng)看https://blog.csdn.net/u010530...
java里如何實(shí)現(xiàn)零拷貝呢?
這就要說(shuō)起java nio中的FileChannel.transferTo()方法了,該方法是把FileChannel中的數(shù)據(jù)利用零靠的技術(shù)轉(zhuǎn)移到另一個(gè)channel。這另一個(gè)channel往往是FileChannel,不過(guò)SocketChannel也是可以的:)。
簡(jiǎn)單實(shí)現(xiàn)(靜態(tài)下載文件,不能根據(jù)用戶指令來(lái)更改下載的文件。)
代碼如下:
單線程版本:
package qiuqi.filedownloadtest; import java.io.FileInputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.*; import java.util.Iterator; public class FileServer { public static void main(String[] args) throws IOException { startServer(); } public static void startServer() throws IOException { ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.bind(new InetSocketAddress(9999)); serverSocketChannel.configureBlocking(false); Selector selector = Selector.open(); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while (selector.select() > 0) { Iteratoriterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); iterator.remove(); if(key.isAcceptable()) { SocketChannel socketChannel = serverSocketChannel.accept(); try (FileInputStream in = new FileInputStream("C:UsersdellDesktopOL手機(jī)數(shù)據(jù)(1).rar")){ long size = in.available(); long num = 0; long begin = 0; while ( (num = in.getChannel().transferTo(begin,size,socketChannel))!=0) { size-=num; begin += num; } socketChannel.close(); } catch (IOException e){e.printStackTrace();} } } } } }
多線程版本:
package qiuqi.filedownloadtest; import java.io.FileInputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.*; import java.util.Iterator; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class FileServer { static ExecutorService threadpool = Executors.newCachedThreadPool(); public static void main(String[] args) throws IOException { startServer(); } public static void startServer() throws IOException { ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.bind(new InetSocketAddress(9999)); serverSocketChannel.configureBlocking(false); Selector selector = Selector.open(); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while (selector.select() > 0) { Iteratoriterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); iterator.remove(); if(key.isAcceptable()) { SocketChannel socketChannel = serverSocketChannel.accept(); threadpool.execute(new Runnable() { @Override public void run() { try (FileInputStream in = new FileInputStream("C:UsersdellDesktopOL手機(jī)數(shù)據(jù)(1).rar")){ long size = in.available(); long num = 0; long begin = 0; while ( (num = in.getChannel().transferTo(begin,size,socketChannel))!=0) { size-=num; begin += num; } socketChannel.close(); } catch (IOException e){e.printStackTrace();} } }); } } } } }
代碼就不講解了。如果學(xué)過(guò)java nio,那么理解上面的程序輕而易舉。
如果不熟悉java nio的服務(wù)器編程那么請(qǐng)先學(xué)習(xí)再來(lái)觀看。
最后我想說(shuō),java NIO真的是NEW IO即新的IO,而不是NonBlocking IO即非阻塞IO。因?yàn)樵谶@套體系里,不僅僅提供了非阻塞的編程模型,而且提供了類(lèi)似零拷貝,內(nèi)存映射這樣的新技術(shù)(對(duì)于操作系統(tǒng)來(lái)說(shuō)早就有了)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/73543.html
摘要:如果什么事都沒(méi)得做,它也不會(huì)死循環(huán),它會(huì)將線程休眠起來(lái),直到下一個(gè)事件來(lái)了再繼續(xù)干活,這樣的一個(gè)線程稱(chēng)之為線程。而請(qǐng)求處理邏輯既可以使用單獨(dú)的線程池進(jìn)行處理,也可以跟放在讀寫(xiě)線程一塊處理。 Netty到底是什么 從HTTP說(shuō)起 有了Netty,你可以實(shí)現(xiàn)自己的HTTP服務(wù)器,F(xiàn)TP服務(wù)器,UDP服務(wù)器,RPC服務(wù)器,WebSocket服務(wù)器,Redis的Proxy服務(wù)器,MySQL的P...
摘要:而每個(gè)文件系統(tǒng)又可以設(shè)置不同的調(diào)度算法,另外,還有虛擬內(nèi)存缺頁(yè)中斷帶來(lái)的性能毛刺良心的提供了調(diào)優(yōu)的腳本,這點(diǎn)做的不錯(cuò)跑題了。測(cè)試環(huán)境核線程內(nèi)存磁盤(pán)讀寫(xiě)左右虛擬內(nèi)存未關(guān)閉,大小測(cè)試注意點(diǎn)為了防止緩存的影響,每次都生成一個(gè)新的文件進(jìn)行讀取。 前言 Java 在 JDK 1.4 引入了 ByteBuffer 等 NIO 相關(guān)的類(lèi),使得 Java 程序員可以拋棄基于 Stream ,從而使用基...
摘要:一旦某個(gè)事件觸發(fā),相應(yīng)的則會(huì)被調(diào)用,并進(jìn)行處理。事實(shí)上,內(nèi)部的連接處理協(xié)議編解碼超時(shí)等機(jī)制,都是通過(guò)完成的。開(kāi)啟源碼之門(mén)理解了的事件驅(qū)動(dòng)機(jī)制,我們現(xiàn)在可以來(lái)研究的各個(gè)模塊了。 Netty是什么 大概用Netty的,無(wú)論新手還是老手,都知道它是一個(gè)網(wǎng)絡(luò)通訊框架。所謂框架,基本上都是一個(gè)作用:基于底層API,提供更便捷的編程模型。那么通訊框架到底做了什么事情呢?回答這個(gè)問(wèn)題并不太容易,我們...
摘要:豐富的緩存數(shù)據(jù)結(jié)構(gòu)使用它自己的緩存來(lái)表示字節(jié)序列而不是的。針對(duì)有一個(gè)定義良好的事件模型。有一些協(xié)議是多層的建立在其他低級(jí)協(xié)議基礎(chǔ)上。此外,甚至不是完全線程安全的。協(xié)議由標(biāo)準(zhǔn)化為。協(xié)議緩存整合是一個(gè)高效二進(jìn)制協(xié)議的快速實(shí)現(xiàn)。 Chapter 2、結(jié)構(gòu)概覽 這一節(jié)我們將確認(rèn)Netty提供的核心功能是什么,以及它們?cè)趺礃?gòu)成一個(gè)完整的網(wǎng)絡(luò)應(yīng)用開(kāi)發(fā)堆棧。 1、豐富的緩存數(shù)據(jù)結(jié)構(gòu) Netty使用它...
摘要:前言從字面意思理解就是數(shù)據(jù)不需要來(lái)回的拷貝,大大提升了系統(tǒng)的性能這個(gè)詞我們也經(jīng)常在,,,等框架中聽(tīng)到,經(jīng)常作為其提升性能的一大亮點(diǎn)下面從的幾個(gè)概念開(kāi)始,進(jìn)而在分析零拷貝。 前言 從字面意思理解就是數(shù)據(jù)不需要來(lái)回的拷貝,大大提升了系統(tǒng)的性能;這個(gè)詞我們也經(jīng)常在java nio,netty,kafka,RocketMQ等框架中聽(tīng)到,經(jīng)常作為其提升性能的一大亮點(diǎn);下面從I/O的幾個(gè)概念開(kāi)始,...
閱讀 1990·2021-09-22 16:05
閱讀 9255·2021-09-22 15:03
閱讀 2880·2019-08-30 15:53
閱讀 1698·2019-08-29 11:15
閱讀 903·2019-08-26 13:52
閱讀 2348·2019-08-26 11:32
閱讀 1798·2019-08-26 10:38
閱讀 2562·2019-08-23 17:19