1. 程式人生 > >Java NIO網路程式設計

Java NIO網路程式設計

javaNIO和傳統BIO的區別:

  1. Java NIO和IO之間第一個最大的區別是,IO是面向流的,NIO是面向緩衝區的。 Java IO面向流意味著每次從流中讀一個或多個位元組,直至讀取所有位元組,它們沒有被快取在任何地方。此外,它不能前後移動流中的資料。如果需要前後移動從流中讀取的資料,需要先將它快取到一個緩衝區。 Java NIO的緩衝導向方法略有不同。資料讀取到一個它稍後處理的緩衝區,需要時可在緩衝區中前後移動。這就增加了處理過程中的靈活性。但是,還需要檢查是否該緩衝區中包含所有您需要處理的資料。而且,需確保當更多的資料讀入緩衝區時,不要覆蓋緩衝區裡尚未處理的資料。
  2. Java IO的各種流是阻塞的。這意味著,當一個執行緒呼叫read() 或 write()時,該執行緒被阻塞,直到有一些資料被讀取,或資料完全寫入。該執行緒在此期間不能再幹任何事情了。 Java NIO的非阻塞模式,使一個執行緒從某通道傳送請求讀取資料,但是它僅能得到目前可用的資料,如果目前沒有資料可用時,就什麼都不會獲取。而不是保持執行緒阻塞,所以直至資料變的可以讀取之前,該執行緒可以繼續做其他的事情。 非阻塞寫也是如此。一個執行緒請求寫入一些資料到某通道,但不需要等待它完全寫入,這個執行緒同時可以去做別的事情。 執行緒通常將非阻塞IO的空閒時間用於在其它通道上執行IO操作,所以一個單獨的執行緒現在可以管理多個輸入和輸出通道(channel)。

NIO的幾個相關的概念:
Buffer(緩衝區) Channel(管道) Selector(多路複用器)

Buffer的基本操作:

public class TestBuffer {

    public static void main(String[] args) {

        // 1 基本操作

        //建立指定長度的緩衝區
        IntBuffer buf = IntBuffer.allocate(10);
        buf.put(13);// position位置:0 - > 1
        buf.put(21);// position位置:1 - > 2
buf.put(35);// position位置:2 - > 3 //把位置復位為0,也就是position位置:3 - > 0 buf.flip(); System.out.println("使用flip復位:" + buf); System.out.println("容量為: " + buf.capacity()); //容量一旦初始化後不允許改變(warp方法包裹陣列除外) System.out.println("限制為: " + buf.limit()); //由於只裝載了三個元素,所以可讀取或者操作的元素為3 則limit=3
System.out.println("獲取下標為1的元素:" + buf.get(1)); System.out.println("get(index)方法,position位置不改變:" + buf); buf.put(1, 4); System.out.println("put(index, change)方法,position位置不變:" + buf);; for (int i = 0; i < buf.limit(); i++) { //呼叫get方法會使其緩衝區位置(position)向後遞增一位 System.out.print(buf.get() + "\t"); } System.out.println("buf物件遍歷之後為: " + buf); // 2 wrap方法使用 /** // wrap方法會包裹一個數組: 一般這種用法不會先初始化快取物件的長度,因為沒有意義,最後還會被wrap所包裹的陣列覆蓋掉。 // 並且wrap方法修改緩衝區物件的時候,陣列本身也會跟著發生變化。 int[] arr = new int[]{1,2,5}; IntBuffer buf1 = IntBuffer.wrap(arr); System.out.println(buf1); IntBuffer buf2 = IntBuffer.wrap(arr, 0 , 2); //這樣使用表示容量為陣列arr的長度,但是可操作的元素只有實際進入快取區的元素長度 System.out.println(buf2); */ // 3 其他方法 /** IntBuffer buf1 = IntBuffer.allocate(10); int[] arr = new int[]{1,2,5}; buf1.put(arr); System.out.println(buf1); //一種複製方法 IntBuffer buf3 = buf1.duplicate(); System.out.println(buf3); //設定buf1的位置屬性 //buf1.position(0); buf1.flip(); System.out.println(buf1); System.out.println("可讀資料為:" + buf1.remaining()); int[] arr2 = new int[buf1.remaining()]; //將緩衝區資料放入arr2陣列中去 buf1.get(arr2); for(int i : arr2){ System.out.print(Integer.toString(i) + ","); } */ } }