nio為什麼不適合文件上傳場景
① 我用JAVA NIO 來復制文件,但沒有發現和傳統的流的方式來操作有明顯的優勢,為什麼呢
好好讀讀Thinking in java文檔,從1.5開始,Java對InputStream/OutputStream 進行了重新改寫,用的就是NIO,因此,就算你不顯示聲明要用NIO,只要你的類繼承了InputStream/OutputStream就已經在用NIO了,不信的話這樣做
FileChannel channel=new FileInputStream.getChannel();
如果XXStream不用NIO構造,如何返回一個Channel的對象?
② 在java中使用io,nio,aio的應用場景,有什麼優劣勢
nio是面向塊的,先把數據搬過來,先存到緩存區裡面,如果線程要用從緩存區拿。所以線程不需要時刻盯著io了,可以先做一些其他的事情,過幾天再來看一下緩存。是同步非阻塞的。因此,nio里有Buffer類作為緩沖區,Channel(通道)相當於io里的steam的抽象,Selector是nio提供的管理多個Channel的工具。nio出現也是因為io漸漸成為一些程序速度的瓶頸。
③ Java中BIO,NIO和AIO的區別和應用場景
Reactor and Proactor
IO讀寫時,多路復用機制都會依賴對一個事件多路分離器,負責把源事件的IO 事件分離出來,分別到相應的read/write事件分離器。涉及到事件分離器的兩種模式分別就是 Reactor和Proactor,Reactor是基於同步IO的,Proactor是基於非同步IO的。
在Reactor模式中,事件分離者等待某個事件或者可應用或個操作的狀態發生(比如文件描述符可讀寫,或者是socket可讀寫),事件分離者就把這個事件傳給事先注冊的事件處理函數或者回調函數,由後者來做實際的讀寫操作。
④ java nio 疑問
主要原因是:客戶端自己關閉了連接(沒有調用SocketChannel的close方法),伺服器還在read事件中,這個時候讀取客戶端的時候會報錯。
解決辦法,在客戶端合適的時候,調用SocketChannel的close方法,同時伺服器讀取事件增加如下邏輯:
count = client.read(receivebuffer);
if(count==-1){
System.out.println(count);
client.close();
} else {
如果伺服器沒有client.close,則一直System.out.println(count)
所以先客戶端調用close,然後伺服器在read事件裡面讀取返回是不是-1,如果是,調用伺服器這邊客戶端的引用的close方法,這樣兩邊的SocketChannel都關閉了。
希望能夠幫助到你,望採納!
⑤ java中IO和NIO的區別和適用場景
java.NIO包里包括三個基本的組件
lbuffer:因為NIO是基於緩沖的,所以buffer是最底層的必要類,這也是IO和NIO的根本不同,雖然stream等有buffer開頭的擴展類,但只是流的包裝類,還是從流讀到緩沖區,而NIO卻是直接讀到buffer中進行操作。
因為讀取的都是位元組,所以在操作文字時,要用charset類進行編解碼操作。
lchannel:類似於IO的stream,但是不同的是除了FileChannel,其他的channel都能以非阻塞狀態運行。FileChannel執行的是文件的操作,可以直接DMA操作內存而不依賴於CPU。其他比如socketchannel就可以在數據准備好時才進行調用。
lselector:用於分發請求到不同的channel,這樣才能確保channel不處於阻塞狀態就可以收發消息。
面向流與面向緩沖
Java NIO和IO之間第一個最大的區別是,IO是面向流的,NIO是面向緩沖區的。Java
IO面向流意味著每次從流中讀一個或多個位元組,直至讀取所有位元組,它們沒有被緩存在任何地方。此外,它不能前後移動流中的數據。如果需要前後移動從流中讀取的數據,需要先將它緩存到一個緩沖區。Java NIO的緩沖導向方法略有不同。數據讀取到一個它稍後處理的緩沖區,需要時可在緩沖區中前後移動。這就增加了處理過程中的靈活性。但是,還需要檢查是否該緩沖區中包含所有您需要處理的數據。而且,需確保當更多的數據讀入緩沖區時,不要覆蓋緩沖區里尚未處理的數據。
補充一點:NIO的buffer可以使用直接內存緩沖區,該緩沖區不在JVM中,性能會比JVM的緩沖區略好,不過會增加相應的垃圾回收的負擔,因為JVM緩沖區的性能已經足夠好,所以除非在對緩沖有特別要求的地方使用直接緩沖區,盡量使用JVM緩沖。
阻塞與非阻塞
Java IO是阻塞式的操作,當一個inputstream或outputstream在進行read()或write()操作時,是一直處於等待狀態的,直到有數據讀/寫入後才進行處理.而NIO是非阻塞式的,當進行讀寫操作時,只會返回當前已經准備好的數據,沒有就返回空,這樣當前線程就可以處理其他的事情,提高了資源的使用率.
與傳統IO的優勢
在老的IO包中,serverSocket和socket都是阻塞式的,因此一旦有大規模的並發行為,而每一個訪問都會開啟一個新線程。這時會有大規模的線程上下文切換操作(因為都在等待,所以資源全都被已有的線程吃掉了),這時無論是等待的線程還是正在處理的線程,響應率都會下降,並且會影響新的線程。
而NIO包中的serverSocket和socket就不是這樣,只要注冊到一個selector中,當有數據放入通道的時候,selector就會得知哪些channel就緒,這時就可以做響應的處理,這樣服務端只有一個線程就可以處理大部分情況(當然有些持續性操作,比如上傳下載一個大文件,用NIO的方式不會比IO好)。
通過兩個圖的比較,可以看出IO是直連的,每個請求都給一條線程來處理,但是NIO卻是基於反應堆(selector)來處理,直到讀寫的數據准備好後,才會通知相應的線程來進行處理。一言以蔽之:「selector不會讓channel白占資源,沒事的時候給我去睡覺。」
PS:NIO基於位元組進行傳輸,在IO時要注意decode/encode。
更具體的信息請參閱:http://blog.csdn.net/zhansong_1987/article/details/45873861
⑥ 有了java.nio還有用java.io的必要嗎
有必要
Java NIO和IO之間的主要差別,我會更詳細地描述表中每部分的差異
IO NIO
面向流 面向緩沖
阻塞IO 非阻塞IO
無 選擇器
面向流與面向緩沖
Java NIO和IO之間第一個最大的區別是,IO是面向流的,NIO是面向緩沖區的。 Java IO面向流意味著每次從流中讀一個或多個位元組,直至讀取所有位元組,它們沒有被緩存在任何地方。此外,它不能前後移動流中的數據。如果需要前後移動從流中讀取的數據,需要先將它緩存到一個緩沖區。 Java NIO的緩沖導向方法略有不同。數據讀取到一個它稍後處理的緩沖區,需要時可在緩沖區中前後移動。這就增加了處理過程中的靈活性。但是,還需要檢查是否該緩沖區中包含所有您需要處理的數據。而且,需確保當更多的數據讀入緩沖區時,不要覆蓋緩沖區里尚未處理的數據。
阻塞與非阻塞IO
Java IO的各種流是阻塞的。這意味著,當一個線程調用read() 或 write()時,該線程被阻塞,直到有一些數據被讀取,或數據完全寫入。該線程在此期間不能再干任何事情了。 Java NIO的非阻塞模式,使一個線程從某通道發送請求讀取數據,但是它僅能得到目前可用的數據,如果目前沒有數據可用時,就什麼都不會獲取。而不是保持線程阻塞,所以直至數據變的可以讀取之前,該線程可以繼續做其他的事情。 非阻塞寫也是如此。一個線程請求寫入一些數據到某通道,但不需要等待它完全寫入,這個線程同時可以去做別的事情。 線程通常將非阻塞IO的空閑時間用於在其它通道上執行IO操作,所以一個單獨的線程現在可以管理多個輸入和輸出通道(channel)。
選擇器(Selectors)
Java NIO的選擇器允許一個單獨的線程來監視多個輸入通道,你可以注冊多個通道使用一個選擇器,然後使用一個單獨的線程來「選擇」通道:這些通道里已經有可以處理的輸入,或者選擇已准備寫入的通道。這種選擇機制,使得一個單獨的線程很容易來管理多個通道。
NIO和IO如何影響應用程序的設計
無論您選擇IO或NIO工具箱,可能會影響您應用程序設計的以下幾個方面:
1.對NIO或IO類的API調用。
2.數據處理。
3.用來處理數據的線程數。
API調用
當然,使用NIO的API調用時看起來與使用IO時有所不同,但這並不意外,因為並不是僅從一個InputStream逐位元組讀取,而是數據必須先讀入緩沖區再處理。
⑦ io和nio的文件讀取方式的不同
io,也稱old io,讀取文件主要通過流,從磁碟上一個一個字元的讀,效率比較低下。
nio,在對文件操作下改進了方式,通過塊讀取,一整塊一整塊的讀取,所以讀取出來的不會是一個字元,而是一個塊,把這些數據放到內存緩沖區內。在進行操作。通過塊的讀取來提高速度。(塊操作,fileChannel)
內存映射,MappedByteBuffer,這個主要是通過內存映射,即利用虛擬內存(把文件某一部分當成內存),直接操作文件,對於一些要在內存中大塊操作的文件,比如1G的文件
你要在內存中操作200M的部分,,把200M讀到物理內存是比較耗內存和CPU的,不如直接把那部分文件虛擬成內存直接操作。
下面是對用以上三個文式對一個300M的文件進行讀取,並寫入另一個文件的測試:
1. inputstream CPU5.6% 內存2.6M costTime:4.039S 使用緩沖區byte:4kb
2. filechannel CPU1.3% 內存2.6M costTime:3.359S 使用緩沖區byte:0(transferTo方式)
3. MappedByteBuffer CPU6.9% 內存2.4M costTime:6.966S 內存映射:300M
可見對大文件塊讀取是最好的;如果要直接操作文件的很大的一部分的內容,則比較適合MappedByteBuffer ;如讀取很小的內容,比如8B的內容,inputStream可能是最好的。
代碼如下,選幾個文件自已試下。使用jdk自帶JConsole進行觀察。
public class Test {
public static void main(String[] args)throws Exception{
File ff=new File("F:/workspace/pureMQ/src/mq/pure/file/cc.rar");
File[] f=new File[7];
File[] f_write=new File[7];
Thread.sleep(15000);
for(int i=0;i<7;i++){
f[i]=new File("F:/workspace/pureMQ/src/mq/pure/file/1"+(i+1)+".jpg");
}
for(int i=0;i<7;i++){
f_write[i]=new File("F:/workspace/pureMQ/src/mq/pure/file/"+i+".jpg");
if(!f_write[i].exists()){
f_write[i].createNewFile();
}
}
f[0]=ff;
long begin=System.currentTimeMillis();
int choice=1;
for(int i=0;i<7;i++){
switch(choice){
case 1:
System.out.println("1");
InputStream ips=new FileInputStream(f[i]);
OutputStream ops=new FileOutputStream(f_write[i]);
byte[] b=new byte[4096];
int index;
while((index=ips.read(b))!=-1){
ops.write(b);
}
if(ips!=null){
ips.close();
}
if(ops!=null){
ops.close();
}
break;
case 2:
System.out.println("2");
RandomAccessFile raf=new RandomAccessFile(f[i],"r");
RandomAccessFile raf_write=new RandomAccessFile(f_write[i],"rw");
FileChannel fc=raf.getChannel();
FileChannel fc_write=raf_write.getChannel();
fc.transferTo(0, fc.size(), fc_write);
fc.close();
fc_write.close();
raf.close();
raf_write.close();
break;
case 3:
System.out.println("3");
RandomAccessFile raf2=new RandomAccessFile(f[i],"r");
RandomAccessFile raf2_write=new RandomAccessFile(f_write[i],"rwd");
FileChannel fc2=raf2.getChannel();
FileChannel fc2_write=raf2_write.getChannel();
MappedByteBuffer mbb=fc2_write.map(MapMode.READ_WRITE, 0, fc2.size());
ByteBuffer bb=ByteBuffer.allocate(4096);
while(fc2.read(bb)!=-1){
bb.flip();
mbb.put(bb);
bb.compact();
}
mbb.force();
fc2.close();
fc2_write.close();
raf2.close();
raf2_write.close();
break;
default:
break;
}
}
long end=System.currentTimeMillis();
System.out.println("all time cost:"+ (end-begin));
}
}
⑧ BIO、NIO、AIO 有什麼區別
BIO是一個連接一個線程。
NIO是一個請求一個線程。
AIO是一個有效請求一個線程。
⑨ 什麼是NIO框架
Java NIO框架MINA用netty性能和鏈接數、並發等壓力測試參數好於mina。
特點:
1。NIO彌補了原來的I/O的不足,它再標准java代碼中提供了高速和面向塊的I/O
原力的I/O庫與NIO最重要的區別是數據打包和傳輸方式的不同,原來的I/O以流的方式處理數據,而NIO以塊的方式處理數據;
2.NIO以通道channel和緩沖區Buffer為基礎來實現面向塊的IO數據處理,MINA是開源的。
JavaNIO非堵塞應用通常適用用在I/O讀寫等方面,我們知道,系統運行的性能瓶頸通常在I/O讀寫,包括對埠和文件的操作上,過去,在打開一個I/O通道後,read()將一直等待在埠一邊讀取位元組內容,如果沒有內容進來,read()也是傻傻的等,這會影響我們程序繼續做其他事情,那麼改進做法就是開設線程,讓線程去等待,但是這樣做也是相當耗費資源的。
Java NIO非堵塞技術實際是採取Reactor模式,或者說是Observer模式為我們監察I/O埠,如果有內容進來,會自動通知我們,這樣,我們就不必開啟多個線程死等,從外界看,實現了流暢的I/O讀寫,不堵塞了。
Java NIO出現不只是一個技術性能的提高,會發現網路上到處在介紹它,因為它具有里程碑意義,從JDK1.4開始,Java開始提高性能相關的功能,從而使得Java在底層或者並行分布式計算等操作上已經可以和C或Perl等語言並駕齊驅。
如果至今還是在懷疑Java的性能,說明思想和觀念已經完全落伍了,Java一兩年就應該用新的名詞來定義。從JDK1.5開始又要提供關於線程、並發等新性能的支持,Java應用在游戲等適時領域方面的機會已經成熟,Java在穩定自己中間件地位後,開始蠶食傳統C的領域。
原理:
NIO 有一個主要的類Selector,這個類似一個觀察者,只要我們把需要探知socketchannel告訴Selector,我們接著做別的事情,當有事件發生時,他會通知我們,傳回一組SelectionKey,我們讀取這些Key,就會獲得我們剛剛注冊過的socketchannel,然後,我們從這個Channel中讀取數據,放心,包準能夠讀到,接著我們可以處理這些數據。Selector內部原理實際是在做一個對所注冊的channel的輪詢訪問,不斷的輪詢(目前就這一個演算法),一旦輪詢到一個channel有所注冊的事情發生。比如數據來了,他就會站起來報告,交出一把鑰匙,讓我們通過這把鑰匙來讀取這個channel的內容。在使用上,也在分兩個方向,一個是線程處理,一個是用非線程,後者比較簡單。