java nio提供了一套稱爲I/O多路複用的編程範式,那麼什麼叫作I/O多路複用呢?
所謂的I/O多路複用,從字面意思上來理解,就是:
有多個I/O操做(或是寫,或是讀,或是請求),這多個I/O操做都共用一個邏輯流。
爲了講清複用的是什麼,首先得先說明一下邏輯流的概念。
邏輯流是什麼?這裏的邏輯流和操做系統中"線程是進程的一個邏輯流"是一個意思。
下面的就是一個邏輯流:java
{ int a = 5; int b a*a; double c = a/b; }
下面又是一個邏輯流:linux
{ long b = 5; int c = b+3; }
若是在一個進程中,若是沒有線程,那麼程序是順序執行的,那麼全部的代碼都是屬於一個邏輯流。
好比說,上面的兩端代碼,若是合在一個進程當中,它們必定是這種結構:編程
{ int a = 5; int b a*a; double c = a/b; } .... { long b = 5; int c = b+3; }
或是網絡
{ long b = 5; int c = b+3; } .... { int a = 5; int b a*a; double c = a/b; }
也就是說它們必定屬於一個邏輯流(一個順序結構)。
理解了這個,那麼所謂的I/O複用,指的就是在一個邏輯流裏處理多個I/O事件!!!
如何作到?利用Selector多路複用器,輪詢監聽各路I/O,若是一旦有I/O事件發生,那麼就去處理,不然程序阻塞。
來看一個程序,加深理解:多線程
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) { Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); iterator.remove(); if(key.isAcceptable()) { System.out.println("收到鏈接這個I/O事件"); catch (IOException e){e.printStackTrace();} } } } } }
這是一個監聽網絡I/O的多路複用程序,java中只能監聽網絡I/O,不能監聽標準輸入輸出等I/O(不過這些在linux裏均可以)。
咱們發現,這個程序的原理就是開啓一個網絡I/O類,ServerSocketChannel,把它註冊到Selector(選擇器)上,而後選擇器就開始
輪詢,直到發現一個I/O事件,因而就進入第一個while循環進行處理,不然一直阻塞在select()>0處。
這是一個極其簡陋的程序,可是它揭示了多路複用的真正內涵,也就是用一個邏輯流監聽,處理多個I/O(不過處理程序其實能夠開啓多線程,也就是指第一個while循環裏的部分)。
這就是I/O多路複用!!!操作系統