<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    DANCE WITH JAVA

    開發(fā)出高質(zhì)量的系統(tǒng)

    常用鏈接

    統(tǒng)計(jì)

    積分與排名

    好友之家

    最新評(píng)論

    探索Java NIO的歷程

    探索Java NIO的歷程
    前段時(shí)間有些時(shí)間,打算看看NIO的東西,本來以為很快可以了解的東西,卻用了很多時(shí)間。
    首先Goole NIO可以看到很多的教程,非阻塞,Buffer,內(nèi)存映射,塊讀取前三個(gè)很快就有所了解
    嘗試著寫了些小程序,學(xué)習(xí)東西的時(shí)候總喜歡寫點(diǎn)小例子。
    唯獨(dú)塊讀取沒有找到對(duì)應(yīng)的東西。(在過程中,主要看了IBM 的NIO入門)

    首先,IBM NIO入門中的語句
    --------------------------------------------------------------------------------
    原來的 I/O 庫(在 java.io.*中) 與 NIO 最重要的區(qū)別是數(shù)據(jù)打包和傳輸?shù)姆绞健U缜懊嫣岬降模?br />原來的 I/O 以流的方式處理數(shù)據(jù),而 NIO 以塊的方式處理數(shù)據(jù)。 面向流 的 I/O 系統(tǒng)一次一個(gè)字節(jié)地處
    理數(shù)據(jù)。一個(gè)輸入流產(chǎn)生一個(gè)字節(jié)的數(shù)據(jù),一個(gè)輸出流消費(fèi)一個(gè)字節(jié)的數(shù)據(jù)。為流式數(shù)據(jù)創(chuàng)建過濾器非常容易。鏈接幾個(gè)過濾器,以便每個(gè)過濾器只負(fù)責(zé)單個(gè)復(fù)雜處理機(jī)制的一部分,這樣也是相對(duì)簡(jiǎn)單的。不利的一面是,面向流的 I/O 通常相當(dāng)慢。 一個(gè) 面向塊 的 I/O 系統(tǒng)以塊的形式處理數(shù)據(jù)。每一個(gè)操作都在一步中產(chǎn)生或者消費(fèi)一個(gè)數(shù)據(jù)塊。按塊處理數(shù)據(jù)比按(流式的)字節(jié)處理數(shù)據(jù)要快得多。但是面向塊的 I/O 缺少一些面向流的I/O 所具有的優(yōu)雅性和簡(jiǎn)單性。
    --------------------------------------------------------------------------------
    首先簡(jiǎn)單的印象是NIO快,所以想寫個(gè)程序驗(yàn)證一下.如下復(fù)制:

    ?

    ?1 public ? static ? void ?test2(String?name1,?String?name2)? {
    ?2 ???????? long ?start? = ?System.currentTimeMillis();
    ?3 ???????? try ? {
    ?4 ????????????FileInputStream?fis? = ? new ?FileInputStream(name1);
    ?5 ????????????FileOutputStream?fos? = ? new ?FileOutputStream(name2);
    ?6 ???????????? byte []?buf? = ? new ? byte [ 8129 ];
    ?7 ???????????? while ?( true )? {????????????????
    ?8 ???????????????? int ?n? = ?fis.read(buf);
    ?9 ???????????????? if ?(n? == ? - 1 )? {
    10 ???????????????????? break ;
    11 ????????????????}

    12 ????????????????fos.write(buf, 0 ,n);
    13 ????????????}

    14 ????????????fis.close();
    15 ????????????fos.close();
    16 ????????}
    ? catch ?(Exception?e)? {
    17 ????????????e.printStackTrace();
    18 ????????}

    19 ???????? long ?end? = ?System.currentTimeMillis();
    20 ???????? long ?time? = ?end? - ?start;
    21 ????????System.out.println(time);
    22 ????}

    23 ????
    24 ???? public ? static ? void ?test3(String?name1,?String?name2)? {
    25 ???????? long ?start? = ?System.currentTimeMillis();
    26 ???????? try ? {
    27 ????????????FileInputStream?in? = ? new ?FileInputStream(name1);
    28 ????????????FileOutputStream?out? = ? new ?FileOutputStream(name2);
    29 ????????????FileChannel?fc1? = ?in.getChannel();
    30 ????????????FileChannel?fc2? = ?out.getChannel();
    31 ????????????ByteBuffer?bb? = ?ByteBuffer.allocate( 8129 );
    32 ???????????? while ?( true )? {
    33 ????????????????bb.clear();
    34 ???????????????? int ?n? = ?fc1.read(bb);
    35 ???????????????? if ?(n? == ? - 1 )? {
    36 ???????????????????? break ;
    37 ????????????????}

    38 ????????????????bb.flip();
    39 ????????????????fc2.write(bb);
    40 ????????????}

    41 ????????????fc1.close();
    42 ????????????fc2.close();
    43 ????????}
    ? catch ?(IOException?e)? {
    44
    45 ????????}

    46 ???????? long ?end? = ?System.currentTimeMillis();
    47 ???????? long ?time? = ?end? - ?start;
    48 ????????System.out.println(time);
    49 ????}

    本以為可以結(jié)束,結(jié)果測(cè)試結(jié)果出乎意料,函數(shù)一比函數(shù)二要快,就是說Old IO快于NIO ,從此
    ?也就開始了整個(gè)過程:
    ?為了了解這個(gè)問題,仔細(xì)搜索并仔細(xì)再看IBM 的NIO教程,看到如下這段話
    ?---------------------------------------------
    ?在 JDK 1.4 中原來的 I/O 包和 NIO 已經(jīng)很好地集成了。 java.io.* 已經(jīng)以 NIO 為基礎(chǔ)重新實(shí)現(xiàn)了,
    ?所以現(xiàn)在它可以利用 NIO 的一些特性。例如, java.io.* 包中的一些類包含以塊的形式讀寫數(shù)據(jù)的方法,
    ?這使得即使在更面向流的系統(tǒng)中,處理速度也會(huì)更快。 也可以用 NIO 庫實(shí)現(xiàn)標(biāo)準(zhǔn) I/O 功能。例如,
    ?可以容易地使用塊 I/O 一次一個(gè)字節(jié)地移動(dòng)數(shù)據(jù)。但是正如您會(huì)看到的,NIO 還提供了原 I/O 包中所沒有的許多好處。
    ??? ---------------------------------------------
    ??? 所以我想,是否因?yàn)镮nputStream中使用了塊讀取實(shí)現(xiàn)了呢,所以進(jìn)入JDK1.4中的InputStream中
    ??? 看看source,首先引起我注意的是read函數(shù),當(dāng)參數(shù)是一個(gè)byte數(shù)組的時(shí)候,直接調(diào)用的native實(shí)現(xiàn)
    ??? 難道是這個(gè),為了驗(yàn)證,下載了一個(gè)JDK1.3下來,發(fā)現(xiàn)JDK1.3是一樣的。
    ???
    ??? 繼續(xù),我想是否是JVM底層實(shí)現(xiàn)了塊讀取呢,為了證明這個(gè)我用JDK1.3和JDK1.4同時(shí)實(shí)現(xiàn)了類似的函數(shù),??? 測(cè)試的結(jié)果再次出乎意料,性能相差不大.那就不是這個(gè)了。
    ? 為此多方查找資料,未果,為此多寫幾個(gè)函數(shù),好好測(cè)試一下IO的不同。于是有了如下的一些函數(shù)

    ??1 // ?exec
    ??2 ???? public ? static ? void ?test1(String?name1,?String?name2)? {
    ??3 ???????? long ?start? = ?System.currentTimeMillis();
    ??4 ???????? try ? {
    ??5 ????????????String?cmd? = ? " cmd?/c?copy?d:\\out1.txt?d:\\out2.txt " ;
    ??6 ????????????System.out.println(cmd);
    ??7 ????????????Process?p? = ?Runtime.getRuntime().exec(cmd);÷
    ??8 ????????????p.waitFor();
    ??9 ????????}
    ? catch ?(Exception?e)? {
    ?10 ????????????e.printStackTrace();
    ?11 ????????}

    ?12 ???????? long ?end? = ?System.currentTimeMillis();
    ?13 ???????? long ?time? = ?end? - ?start;
    ?14 ????????System.out.println(time);
    ?15 ????}

    ?16
    ?17 ???? // ?old?io
    ?18 ???? public ? static ? void ?test2(String?name1,?String?name2)? {
    ?19 ???????? long ?start? = ?System.currentTimeMillis();
    ?20 ???????? try ? {
    ?21 ????????????FileInputStream?fis? = ? new ?FileInputStream(name1);
    ?22 ????????????FileOutputStream?fos? = ? new ?FileOutputStream(name2);
    ?23 ???????????? while ?( true )? {
    ?24 ???????????????? byte []?buf? = ? new ? byte [ 8129 ];
    ?25 ???????????????? int ?n? = ?fis.read(buf);
    ?26 ???????????????? if ?(n? == ? - 1 )? {
    ?27 ???????????????????? break ;
    ?28 ????????????????}

    ?29 ????????????????fos.write(buf);
    ?30 ????????????}

    ?31 ????????????fis.close();
    ?32 ????????????fos.close();
    ?33 ????????}
    ? catch ?(Exception?e)? {
    ?34 ????????????e.printStackTrace();
    ?35 ????????}

    ?36 ???????? long ?end? = ?System.currentTimeMillis();
    ?37 ???????? long ?time? = ?end? - ?start;
    ?38 ????????System.out.println(time);
    ?39 ????}

    ?40
    ?41 ???? // ?new?io
    ?42 ???? public ? static ? void ?test3(String?name1,?String?name2)? {
    ?43 ???????? long ?start? = ?System.currentTimeMillis();
    ?44 ???????? try ? {
    ?45 ????????????FileInputStream?in? = ? new ?FileInputStream(name1);
    ?46 ????????????FileOutputStream?out? = ? new ?FileOutputStream(name2);
    ?47 ????????????FileChannel?fc1? = ?in.getChannel();
    ?48 ????????????FileChannel?fc2? = ?out.getChannel();
    ?49 ????????????ByteBuffer?bb? = ?ByteBuffer.allocate( 8129 );
    ?50 ???????????? while ?( true )? {
    ?51 ????????????????bb.clear();
    ?52 ???????????????? int ?n? = ?fc1.read(bb);
    ?53 ???????????????? if ?(n? == ? - 1 )? {
    ?54 ???????????????????? break ;
    ?55 ????????????????}

    ?56 ????????????????bb.flip();
    ?57 ????????????????fc2.write(bb);
    ?58 ????????????}

    ?59 ????????????fc1.close();
    ?60 ????????????fc2.close();
    ?61 ????????}
    ? catch ?(IOException?e)? {
    ?62
    ?63 ????????}

    ?64 ???????? long ?end? = ?System.currentTimeMillis();
    ?65 ???????? long ?time? = ?end? - ?start;
    ?66 ????????System.out.println(time);
    ?67 ????}

    ?68
    ?69 ???? // ?fast?copy
    ?70 ???? public ? static ? void ?test4(String?name1,?String?name2)? {
    ?71 ???????? long ?start? = ?System.currentTimeMillis();
    ?72 ???????? try ? {
    ?73 ????????????FileInputStream?in? = ? new ?FileInputStream(name1);
    ?74 ????????????;
    ?75 ????????????FileOutputStream?out? = ? new ?FileOutputStream(name2);
    ?76 ????????????;
    ?77 ????????????FileChannel?fc1? = ?in.getChannel();
    ?78 ????????????FileChannel?fc2? = ?out.getChannel();
    ?79 ????????????ByteBuffer?bb? = ?ByteBuffer.allocateDirect( 8129 );
    ?80 ???????????? while ?( true )? {
    ?81 ????????????????bb.clear();
    ?82 ???????????????? int ?n? = ?fc1.read(bb);
    ?83 ???????????????? if ?(n? == ? - 1 )? {
    ?84 ???????????????????? break ;
    ?85 ????????????????}

    ?86 ????????????????bb.flip();
    ?87 ????????????????fc2.write(bb);
    ?88 ????????????}

    ?89 ????????????fc1.close();
    ?90 ????????????fc2.close();
    ?91 ????????}
    ? catch ?(IOException?e)? {
    ?92
    ?93 ????????}

    ?94 ???????? long ?end? = ?System.currentTimeMillis();
    ?95 ???????? long ?time? = ?end? - ?start;
    ?96 ????????System.out.println(time);
    ?97 ????}

    ?98
    ?99 ???? // ?transfer?,read?and?write?at?same?time
    100 ???? public ? static ? void ?test5(String?name1,?String?name2)? {
    101 ???????? long ?start? = ?System.currentTimeMillis();
    102 ???????? try ? {
    103 ????????????RandomAccessFile?raf1? = ? new ?RandomAccessFile(name1,? " rw " );
    104 ????????????RandomAccessFile?raf2? = ? new ?RandomAccessFile(name2,? " rw " );
    105 ????????????FileChannel?fc1? = ?raf1.getChannel();
    106 ????????????FileChannel?fc2? = ?raf2.getChannel();
    107 ????????????fc1.transferTo( 0 ,?raf1.length(),?fc2);
    108 ????????????fc1.close();
    109 ????????????fc2.close();
    110 ????????}
    ? catch ?(Exception?e)? {
    111 ????????????e.printStackTrace();
    112 ????????}

    113 ???????? long ?end? = ?System.currentTimeMillis();
    114 ???????? long ?time? = ?end? - ?start;
    115 ????????System.out.println(time);
    116 ????}

    首先測(cè)試的文件是一個(gè)30幾M的文件,測(cè)試結(jié)果出乎意料,是否因?yàn)槲募∧??用個(gè)200M的文件再次
    ?測(cè)試一下,結(jié)果更匪夷所思,transfor的方式快些,exec的方式快些,Old IO和NIO相差不大,而且
    ?稍快與NIO,拿到這個(gè)結(jié)果真讓人氣餒,再次查找資料,但都沒有解決自己的疑問,這個(gè)時(shí)候看到了
    ?Think In Java第三版上講到NIO,更讓我興奮的是我看到如下的話,大概意思吧,原文記不住了
    ?"Java NIO在文件讀取和網(wǎng)絡(luò)方面有很大的性能提高,網(wǎng)絡(luò)方面不說,這里說說文件操作"看到這段話
    ?真是高興,因?yàn)門hink In Java一向都是有很多寫的很好的小例子,懷著這種心情,往下看,終于找到了
    ?一個(gè)顯示性能差別小例子,但讓我哭笑不得的是,作者居然是使用的內(nèi)存映射的例子。類似這樣
    ?RandomAccessFile raf1 = new RandomAccessFile(name1, "rw");
    ???FileChannel fc1 = raf1.getChannel();
    ???MappedByteBuffer mbb = fc1.map(FileChannel.MapMode.READ_WRITE, 0,
    ?????1024);
    ?使用內(nèi)存映射來和傳統(tǒng)的IO來對(duì)比讀寫,本來就是個(gè)不公平的事情。內(nèi)存映射的讀取實(shí)際是內(nèi)存讀寫
    ?和傳統(tǒng)IO比肯定有很大差距。到現(xiàn)在,從開始NIO到現(xiàn)在已經(jīng)有1周的時(shí)間了,每天我都會(huì)在工作之余拿出?1-2個(gè)小時(shí)看看NIO,但這個(gè)問題越來越迷離。
    ?
    ?今天有時(shí)間把這個(gè)過程寫出來,一方面感覺過程無奈,寫出來留個(gè)紀(jì)念,另一方面希望和大家交流一下,?如果你沒看過NIO或者沒有作過這個(gè)方面的嘗試,如果你有興趣可以一起探討,如果你了解這個(gè)問題,請(qǐng)?不吝賜教,或給個(gè)提示,或者告訴我我的測(cè)試錯(cuò)在什么地方,不勝感謝。同時(shí),我會(huì)繼續(xù)這個(gè)問題,直到?找到答案。然后會(huì)把答案放上來共享。

    posted on 2006-11-18 23:56 dreamstone 閱讀(11612) 評(píng)論(16)  編輯  收藏 所屬分類: jdk相關(guān)

    評(píng)論

    # re: 探索Java NIO的歷程 2006-11-19 15:49 NCindy

    NIO的目的不是在單個(gè)IO的時(shí)候快過普通I/O,而是在并發(fā)多個(gè)I/O的時(shí)候減少線程的使用量,從而提高整個(gè)系統(tǒng)的可伸縮性。  回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2006-11-19 19:34 dreamstone

    NIO的目的是加速IO,并發(fā)多個(gè)IO時(shí)候減少線程使用量是其中的一個(gè)很重要的部分,這不排除,文章開始我已經(jīng)說了。但是在驗(yàn)證過程中,其它的問題例如非阻塞,例如內(nèi)存映射,有大量的例子,很容易讓人理解,但我提到的問題,并沒有找到答案。我的意思不是說這個(gè)重要,而是疑問在這里。  回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2006-11-19 21:37 NCindy

    看了兩遍,還是不清楚你的問題是啥,呵呵。  回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2006-11-19 21:44 dreamstone

    謝謝你指出問題,也許我說的不夠清楚.
    我的疑問是:
    很多地方(IBM NIO入門教程,Think In Java, google到的教材)都說NIO的文件操作有很大幅度的性能提高.但是我自己寫程序證明不出什么地方提高了,我還沒找到方法可以證明性能提高了。我學(xué)習(xí)東西的一個(gè)習(xí)慣是寫一些小的例子,證明事實(shí)確實(shí)如此,但塊讀取提高性能方面,我確實(shí)沒有做到,寫出的程序要不互相矛盾,要不是反例。
      回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2006-11-19 21:59 NCindy

    其實(shí)讀取文件,除非JDK代碼有問題,否則怎么也不會(huì)有大幅性能提升了。讀文件,完全是磁盤性能問題了。

    下面這段話(來自Java? I/O, 2nd Edition)也許能解決你部分問題:
    Nonblocking I/O is primarily relevant to network connections. Pipe channels that move data between two threads also support nonblocking I/O. File channels don't support it at all because file access doesn't block nearly as often as network channels do, and most modern disk controllers can fill a CPU with data fast enough to keep it satisfied. Furthermore, it's uncommon for one program to read or write hundreds of files simultaneously. However, on network servers, this usage pattern is the rule, not the exception.


      回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2006-11-19 22:08 dreamstone

    首先,謝謝你幫忙解決我的疑問。:)
    然后,這個(gè)問題如果是這樣的話,所有的現(xiàn)象就說的通了,我再看看。謝謝  回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2006-11-20 10:20 demo java

    JDK1.4以上的IO讀取底層使用的實(shí)際上都是NIO,要比較得拿1.3里的OLD IO去比較。  回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2006-11-20 14:18 dreamstone

    樓上看我的文章,我確是拿jdk1.3比較了。  回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2006-11-28 11:09 roygbip

    呵呵,你一定是沒有用對(duì)jdk吧我把你上面方法的2,3,4在jdk1.5的環(huán)境中測(cè)試拷貝一個(gè)20M的文件,時(shí)間,分別是297,453,406,不過方法2在jdk1.3的環(huán)境中用時(shí)卻是3969。  回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2006-11-28 11:37 dreamstone

    首先jdk的使用是肯定沒錯(cuò)的,我測(cè)試了很多次,而且反復(fù)確認(rèn)了這個(gè)問題。你的這個(gè)數(shù)據(jù)我測(cè)試出來過,首先說說一些測(cè)試時(shí)候的注意的幾個(gè)問題吧。
    1,不能直接一個(gè)main函數(shù)調(diào)用所有的test(),因?yàn)闀?huì)有內(nèi)存回收的問題。可以嘗試把執(zhí)行順序倒過來,會(huì)發(fā)現(xiàn)所有的測(cè)試數(shù)據(jù)會(huì)有大變化
    2,可以在每個(gè)函數(shù)之間加上System.gc(),但是依然會(huì)有問題,大概的規(guī)律是第一次執(zhí)行慢,第二次快,以后還有快的幾次,然後忽然又變慢。這個(gè)不是虛擬機(jī)load的問題。
    3,可以做如下測(cè)試,只執(zhí)行一個(gè)函數(shù),用手動(dòng)執(zhí)行5-7次,點(diǎn)的快和慢得到的結(jié)果很大差距。
    4,建議用大一點(diǎn)的文件200m,或者更大,因?yàn)檫@樣可以漸少一些特殊因素的影響
    5,多次測(cè)試,去掉怪異的數(shù)值,平均值
    6,這個(gè)問題我現(xiàn)在發(fā)現(xiàn)的最穩(wěn)妥的辦法是,執(zhí)行test1(),等半分鐘,再執(zhí)行另一個(gè),雖然這個(gè)方法是笨的不行,但是確是得出的數(shù)據(jù)穩(wěn)定些,其他的辦法很難得出
    正確的數(shù)據(jù)。
    7,我也嘗試了在linux來測(cè)試,效果也不明顯。  回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2007-07-28 00:06 he

    在單cpu和單硬盤的情況下,你想想,是多線程讀寫文件快,還是單線程快.
    NIO主要用于提高并發(fā)處理的能力(能同時(shí)服務(wù)于更多的客戶,而資源消耗最小),而不是提升速度.  回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2008-05-06 16:05 ztk

    學(xué)習(xí)了
      回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2009-03-05 17:35 zod

    內(nèi)存映射難道不是NIO的長(zhǎng)處嗎
      回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2009-05-03 22:37 C.

    學(xué)習(xí)了  回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2009-06-30 17:41 吳冬冬

    你這也叫使用NIO?
    很搞笑啊,多看看API,不是我打擊你。  回復(fù)  更多評(píng)論   

    # re: 探索Java NIO的歷程 2009-08-16 16:46 QQ124294272

    是啊,selector也沒有  回復(fù)  更多評(píng)論   

    主站蜘蛛池模板: 亚洲av无码成人精品国产| 亚洲人成777在线播放| 国产亚洲精彩视频| 日本高清色本免费现在观看| 亚洲成A∨人片在线观看无码| 精品一区二区三区无码免费视频 | 午夜影视在线免费观看| 亚洲一级大黄大色毛片| 曰批全过程免费视频在线观看| 亚洲综合一区二区| 成人女人A级毛片免费软件| 亚洲一卡2卡4卡5卡6卡残暴在线| 男女超爽刺激视频免费播放| 亚洲成无码人在线观看| 国拍在线精品视频免费观看| 国产午夜亚洲精品| 免费v片在线观看品善网| 一级毛片aaaaaa视频免费看| 亚洲精品乱码久久久久久蜜桃不卡 | 午夜福利不卡片在线播放免费| 亚洲综合无码一区二区痴汉| 韩国欧洲一级毛片免费 | 暖暖在线视频免费视频| 亚洲精品资源在线| 美女被免费视频网站a国产 | 国产亚洲精品美女2020久久| 亚洲乱码国产一区网址| 鲁丝片一区二区三区免费 | 香蕉97超级碰碰碰免费公| 亚洲AV综合永久无码精品天堂| 亚洲一区无码精品色| 91视频免费网址| 日韩国产精品亚洲а∨天堂免| 亚洲性日韩精品一区二区三区| 久久免费视频99| 亚洲AV综合色区无码一二三区| 亚洲高清国产拍精品26U| 啦啦啦中文在线观看电视剧免费版 | 成人网站免费观看| 99麻豆久久久国产精品免费 | 四虎一区二区成人免费影院网址|