Java NIO總結

來源:互聯網
上載者:User

標籤:成功   int   writing   反轉   java nio   select   net   timeout   nal   

一、NIO

NIO是new IO,也是非阻塞IO。有Channel、Selector、Buffer、Pipe、FileLock等類。

Buffer在java.nio包

Channel、Selector、Pipe、FileLock等在java.nio.channels包

 

二、Channel通道

設定非阻塞configureBlocking(false);

註冊選取器register(selector,SelectionKey.OP_XXX)

使用方法read(Buffer) ,write(Buffer)

使用方法open()擷取Channel

  • FileChannel       使用FileInputStream,FileOutputStream,RandomAccessFile或者open(Path path, OpenOption... options)可以擷取channel對象
  • ServerSocketChannel
  • SocketChannel
  • DatagramChannel
  • Pipe.SinkChannel         使用pipe.sink()
  • Pipe.SourceChannel    使用pipe.source()

 

三、Buffer緩衝

除了boolean類型沒有Buffer類,其他七種基礎資料型別 (Elementary Data Type)都有Buffer緩衝。而byte有兩個Buffer緩衝,一個是在堆,一個在檔案的記憶體映射區.

方法clear()  清空Buffer

方法compact()移動Buffer資料到起始位置,設定為position在資料末尾

方法flip() 反轉Buffer,將寫入模式轉成讀模式

方法rewind() 從0開始讀資料

方法hasRemaining()判斷是否還有剩餘資料

ByteBuffer

ShortBuffer

IntBuffer

LongBuffer

FloatBuffer

DoubleBuffer

CharBuffer

MappedByteBuffer        通過FileChannel.map方法產生

 

四、Selector 選取器
Selector selector = Selector.open();channel.configureBlocking(false);SelectionKey key = channel.register(selector,Selectionkey.OP_READ);

select方法

int select()int select(long timeout)int selectNow()

select()阻塞到至少有一個通道在你註冊的事件上就緒了。

select(long timeout)和select()一樣,除了最長會阻塞timeout毫秒(參數)。

selectNow()不會阻塞,不管什麼通道就緒都立刻返回

 

調用Selector.wakeup()方法,阻塞在select()方法上的線程會立馬返回。

用完Selector後調用其close()方法會關閉該Selector,且使註冊到該Selector上的所有SelectionKey執行個體無效。通道本身並不會關閉。

 

五、SelectionKey

Selector四種事件用SelectionKey的四個常量來表示:

SelectionKey.OP_CONNECT

SelectionKey.OP_ACCEPT

SelectionKey.OP_READ

SelectionKey.OP_WRITE

 

在Selector的select方法返回不為0時,擷取SelectionKey

Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator keyIterator = selectedKeys.iterator();while(keyIterator.hasNext()) {
SelectionKey key
= keyIterator.next(); if(key.isAcceptable()) { // a connection was accepted by a ServerSocketChannel. } else if (key.isConnectable()) { // a connection was established with a remote server. } else if (key.isReadable()) { // a channel is ready for reading } else if (key.isWritable()) { // a channel is ready for writing } keyIterator.remove(); //必須移除掉,否則下一次channel還留在selectionkeySet中。}

 

六、Pipe 管道 (1)SinkChannel
Pipe pipe = Pipe.open();Pipe.SinkChannel sinkChannel = pipe.sink();String data = "a sink pipe channel";ByteBuffer buf = ByteBuffer.allocate(50);buf.clear();buf.put(data.getBytes());buf.flip();while(buf.hasRemaining()) {    sinkChannel.write(buf);}

 

(2)SourceChannel
Pipe.SourceChannel sourceChannel = pipe.source();ByteBuffer buf = ByteBuffer.allocate(50);int length = sourceChannel.read(buf);

 

 七、FileLock

FileLock與Lock介面相似,但沒有實現Lock介面

(1)概念

  • 共用鎖定: 共用讀操作,但只能一個寫(讀可以同時,但寫不能)
  • 獨佔鎖: 只有一個讀或一個寫(讀和寫都不能同時)

(2)FileLock FileChannel.lock(long position, long size, boolean shared)

shared的含義:是否使用共用鎖定,一些不支援共用鎖定的作業系統,將自動將共用鎖定改成排它鎖。可以通過調用isShared()方法來檢測獲得的是什麼類型的鎖。

(3) lock()和tryLock()的區別:

lock()阻塞的方法,鎖定範圍可以隨著檔案的增大而增加。無參lock()預設為獨佔鎖;有參lock(0L, Long.MAX_VALUE, true)為共用鎖定。

tryLock()非阻塞,當未獲得鎖時,返回null.

(4)FileLock的生命週期:在調用FileLock.release(),或者Channel.close(),或者JVM關閉

(5)FileLock是安全執行緒的

(6)同一進程內,在檔案鎖沒有被釋放之前,不可以再次擷取。即在release()方法調用前,只能lock()或者tryLock()一次。

        FileChannel channel = null;        FileLock lock=null;        try {            RandomAccessFile raf = new RandomAccessFile("data.txt", "rw");            channel = raf.getChannel();            //獲得鎖方法一:lock(),阻塞的方法,當檔案鎖不可用時,當前進程會被掛起              lock = channel.lock();//無參lock()為獨佔鎖              //lock = channel.lock(0L, Long.MAX_VALUE, true);//有參lock()為共用鎖定,有寫操作會報異常              //獲得鎖方法二:trylock(),非阻塞的方法,當檔案鎖不可用時,tryLock()會得到null值              //do {              //  lock = channel.tryLock();              //} while (null == lock);         } catch (Exception e) {        }finally{            if (lock!=null) {                lock.release();            }            if (channel!=null) {                channel.close();            }        }

 

 八、ServerSocketChannel 伺服器通道
package cn.edu.scau.mk;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;/** * * @author MK */public class Test {    volatile static boolean isFinished = false;    public static void main(String[] args) throws IOException {        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();        serverSocketChannel.socket().bind(new InetSocketAddress(888));        while (!isFinished) {            SocketChannel socketChannel = serverSocketChannel.accept();            //1.阻塞模式            //線程處理socketChannel...            //2.非阻塞模式            if (socketChannel != null) {                //處理socketChannel...            }        }        serverSocketChannel.close();    }}

 

九、SocketChannel TCP通道
package cn.edu.scau.mk;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;/** * * @author MK */public class Test {    volatile static boolean isFinished = false;    public static void main(String[] args) throws IOException {        SocketChannel socketChannel = SocketChannel.open();        socketChannel.configureBlocking(false);//設定為非阻塞        socketChannel.connect(new InetSocketAddress("https://www.baidu.com", 80));        String data = "a socket channel connect";        ByteBuffer buf = ByteBuffer.allocate(48);        buf.clear();        buf.put(data.getBytes());        buf.flip();        while (!socketChannel.finishConnect()) {            //等待串連成功或者做其他的事        }        //非阻塞狀態有可能沒有寫入資料就返回了        while (buf.hasRemaining()) {            socketChannel.write(buf);        }        socketChannel.close();    }}

 

十、DatagramChannel UDP通道
package cn.edu.scau.mk;import java.io.IOException;import java.net.InetSocketAddress;import java.net.SocketAddress;import java.nio.ByteBuffer;import java.nio.channels.DatagramChannel;import java.nio.channels.SocketChannel;/** * * @author MK */public class Test {    volatile static boolean isFinished = false;    public static void main(String[] args) throws IOException {        DatagramChannel channel = DatagramChannel.open();        channel.socket().bind(new InetSocketAddress(888));        //channel.connect(new InetSocketAddress("www.baidu.com", 80));        ByteBuffer buf = ByteBuffer.allocate(48);        buf.clear();        //接收        SocketAddress sa=channel.receive(buf);        //connect通道可以使用read        //int bytesRead = channel.read(buf);        buf.clear();        buf.put("datagram channel".getBytes());        buf.flip();        //發送        int length = channel.send(buf, new InetSocketAddress("www.baidu.com", 80));        //connect通道可以使用write        //channel.write(buf);        channel.close();    }}

 

Java NIO總結

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.