java nio

NIO 是java nonblocking(非堵塞) IO 的簡稱,在jdk1.4 裏提供的新api 。Sun 官方標榜的特性例如如下: 爲所有的原始類型提供(Buffer)緩存支持。字符集編碼解碼解決方式。 Channel :一個新的原始I/O 抽象。 支持鎖和內存映射文件的文件訪問接口。 提供多路(non-bloking) 非堵塞式的高伸縮性網絡I/O 。java

Java NIO非阻塞應用一般適用用在I/O讀寫等方面,咱們知道,系統執行的性能瓶頸一般在I/O讀寫,包含對port和文件的操做上,以前,在打開一個I/O通道後。read()將一直等待在port一邊讀取字節內容。假設沒有內容進來,read()也是傻傻的等,這會影響咱們程序繼續作其它事情,那麼改進作法就是開設線程,讓線程去等待,但是這樣作也是至關耗費資源的。
Java NIO非阻塞技術實際是採取Reactor模式。或者說是Observer模式爲咱們監察I/Oport,假設有內容進來。會本身主動通知咱們。這樣。咱們就沒必要開啓多個線程死等,從外界看,實現了流暢的I/O讀寫,不阻塞了。

mysql

NIO包(java.nio.*)引入了四個關鍵的抽象數據類型,它們共同解決傳統的I/O類中的一些問題。sql


1. Buffer:它是包括數據且用於讀寫的線形表結構。當中還提供了一個特殊類用於內存映射文件的I/O操做。
2. Charset:它提供Unicode字符串影射到字節序列以及逆影射的操做。
3. Channels:包括socket,file和pipe三種管道,它其實是雙向交流的通道。
數據庫


4. Selector:它將多元異步I/O操做集中到一個或多個線程中(它可以被當作是Unix中select()函數或Win32中WaitForSingleEvent()函數的面向對象版本號)。
編程


Package java.nio api

這個包主要定義了 Buffer 及其子類。 Buffer 定義了一個線性存放 primitive type 數據的容器接口。緩存

對於除 boolean 之外的其它 primitive type ,都有一個對應的 Buffer 子類。 ByteBuffer 是當中最重要的一個子類。值得注意的是 Buffer 及其子類都不是線程安全的。安全


Package java.nio.channels網絡

這個包定義了 Channel 的概念。 Channel 表現了一個可以進行 IO 操做的通道(比方。經過 FileChannel 。咱們可以對文件進行讀寫操做)。 java.nio.channels 包括了文件系統和網絡通信相關的 channel 類。這個包經過 Selector 和 SelectableChannel 這兩個類,還定義了一個進行非堵塞( non-blocking ) IO 操做的 API ,這對需要高性能 IO 的應用很重要。非堵塞 IO 贊成應用程序同一時候監控多個 channel 以提升性能。這一功能是經過 Selector 。 SelectableChannel 和 SelectionKey 這 3 個類來實現的。app


Package java.nio.charset

這個包定義了 字符編碼解碼 : 字節碼自己僅僅是一些數字,放到正確的上下文中被正確被解析。向 ByteBuffer 中存放數據時需要考慮字符集的編碼方式,讀取展現 ByteBuffer 數據時涉及對字符集解碼。以咱們最多見的 http 請求爲例,在請求的時候必須對請求進行正確的編碼。在獲得響應時必須對響應進行正確的解碼。


Selector

NIO 有一個基本的類Selector,這個相似一個觀察者,僅僅要咱們把需要探知的socketchannel告訴Selector,咱們接着作別的事情,當有事件發生時。他會通知咱們,傳回一組SelectionKey,咱們讀取這些Key,就會得到咱們剛剛註冊過的socketchannel,而後。咱們從這個Channel中讀取數據。放心,包準能夠讀到,接着咱們能夠處理這些數據。

 

//文件上傳
package tesrt;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Nio {

    /**
     *
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        String infile = "D:\\copy.sql";
        String outfile = "D:\\copy.txt";
        try {
            // 獲取源文件和目標文件的輸入輸出流
            FileInputStream fin = new FileInputStream(infile);
            FileOutputStream fout = new FileOutputStream(outfile);
            // 獲取輸入輸出通道
            FileChannel fcin = fin.getChannel();
            FileChannel fcout = fout.getChannel();

            // 建立緩衝區
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            while (true) {
                // clear方法重設緩衝區,使它可以接受讀入的數據
                buffer.clear();
                // 從輸入通道中將數據讀到緩衝區
                int r = fcin.read(buffer);
                // read方法返回讀取的字節數,可能爲零,假設該通道已到達流的末尾,則返回-1
                if (r == -1) {
                    break;
                }
                // flip方法讓緩衝區可以將新讀入的數據寫入還有一個通道
                buffer.flip();
                // 從輸出通道中將數據寫入緩衝區
                fcout.write(buffer);
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}



//NIO中讀取數據的步驟:1)從FileInputStream中獲得Channel對象;2)建立一個buffer對象;3)從Channel中讀數據到Buffer中;

200M文件讀取 大約2,3分鐘

package tesrt;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Nio {

    public static void main(String args[]) throws Exception {
        int bufSize = 100;
        File fin = new File("D:\\數據庫\\mysql工具\\mysql-5.5.8-win32.msi");
        File fout = new File("D:\\ysql-5.5.8-win32.msi");

        FileChannel fcin = new RandomAccessFile(fin, "r").getChannel();
        ByteBuffer rBuffer = ByteBuffer.allocate(bufSize);

        FileChannel fcout = new RandomAccessFile(fout, "rws").getChannel();
        ByteBuffer wBuffer = ByteBuffer.allocateDirect(bufSize);

        readFileByLine(bufSize, fcin, rBuffer, fcout, wBuffer);

        System.out.print("OK!!!");
    }

    public static void readFileByLine(int bufSize, FileChannel fcin,
            ByteBuffer rBuffer, FileChannel fcout, ByteBuffer wBuffer) {
        String enterStr = "\n";
        try {
            byte[] bs = new byte[bufSize];

            int size = 0;
            StringBuffer strBuf = new StringBuffer("");
            // while((size = fcin.read(buffer)) != -1){
            while (fcin.read(rBuffer) != -1) {
                int rSize = rBuffer.position();
                rBuffer.rewind();
                rBuffer.get(bs);
                rBuffer.clear();
                String tempString = new String(bs, 0, rSize);
                // System.out.print(tempString);
                // System.out.print("<200>");

                int fromIndex = 0;
                int endIndex = 0;
                while ((endIndex = tempString.indexOf(enterStr, fromIndex)) != -1) {
                    String line = tempString.substring(fromIndex, endIndex);
                    line = new String(strBuf.toString() + line);
                    // System.out.print(line);
                    // System.out.print("</over/>");
                    // write to anthone file
                    writeFileByLine(fcout, wBuffer, line);
                    strBuf.delete(0, strBuf.length());
                    fromIndex = endIndex + 1;
                }
                if (rSize > tempString.length()) {
                    strBuf.append(tempString.substring(fromIndex,
                            tempString.length()));
                } else {
                    strBuf.append(tempString.substring(fromIndex, rSize));
                }
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void writeFileByLine(FileChannel fcout, ByteBuffer wBuffer,
            String line) {
        try {
            fcout.write(wBuffer.wrap(line.getBytes()), fcout.size());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}



NIO中另外一個知識點就是無堵塞的Socket編程,這裏就不說了。因爲比較複雜。但是假設咱們真正理解了Selector這個調度者的工做。那麼無堵塞的實現機制咱們差點兒相同就掌握了。

相關文章
相關標籤/搜索