Java NIO总结
NIO是new IO,也是非阻塞IO。有Channel、Selector、Buffer、Pipe、FileLock等類(lèi)。
Buffer在java.nio包
Channel、Selector、Pipe、FileLock等在java.nio.channels包
?
二、Channel通道
設(shè)置非阻塞configureBlocking(false);
注冊(cè)選擇器register(selector,SelectionKey.OP_XXX)
使用方法read(Buffer) ,write(Buffer)
使用方法open()獲取Channel
- FileChannel ? ? ? 使用FileInputStream,FileOutputStream,RandomAccessFile或者open(Path path, OpenOption... options)可以獲取channel對(duì)象
- ServerSocketChannel
- SocketChannel
- DatagramChannel
- Pipe.SinkChannel ? ? ? ? 使用pipe.sink()
- Pipe.SourceChannel ? ?使用pipe.source()
?
三、Buffer緩沖
除了boolean類(lèi)型沒(méi)有Buffer類(lèi),其他七種基本數(shù)據(jù)類(lèi)型都有Buffer緩沖。而byte有兩個(gè)Buffer緩沖,一個(gè)是在堆,一個(gè)在文件的內(nèi)存映射區(qū).
方法clear() ?清空Buffer
方法compact()移動(dòng)Buffer數(shù)據(jù)到起始位置,設(shè)置為position在數(shù)據(jù)末尾
方法flip() 反轉(zhuǎn)Buffer,將寫(xiě)模式轉(zhuǎn)成讀模式
方法rewind() 從0開(kāi)始讀數(shù)據(jù)
方法hasRemaining()判斷是否還有剩余數(shù)據(jù)
ByteBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
CharBuffer
MappedByteBuffer ? ? ? ?通過(guò)FileChannel.map方法產(chǎn)生
?
四、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()阻塞到至少有一個(gè)通道在你注冊(cè)的事件上就緒了。
select(long timeout)和select()一樣,除了最長(zhǎng)會(huì)阻塞timeout毫秒(參數(shù))。
selectNow()不會(huì)阻塞,不管什么通道就緒都立刻返回
?
調(diào)用Selector.wakeup()方法,阻塞在select()方法上的線(xiàn)程會(huì)立馬返回。
用完Selector后調(diào)用其close()方法會(huì)關(guān)閉該Selector,且使注冊(cè)到該Selector上的所有SelectionKey實(shí)例無(wú)效。通道本身并不會(huì)關(guān)閉。
?
五、SelectionKey
Selector四種事件用SelectionKey的四個(gè)常量來(lái)表示:
SelectionKey.OP_CONNECT
SelectionKey.OP_ACCEPT
SelectionKey.OP_READ
SelectionKey.OP_WRITE
?
在Selector的select方法返回不為0時(shí),獲取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接口相似,但沒(méi)有實(shí)現(xiàn)Lock接口
(1)概念
- 共享鎖: 共享讀操作,但只能一個(gè)寫(xiě)(讀可以同時(shí),但寫(xiě)不能)
- 獨(dú)占鎖: 只有一個(gè)讀或一個(gè)寫(xiě)(讀和寫(xiě)都不能同時(shí))
(2)FileLock FileChannel.lock(long position, long size, boolean shared)
shared的含義:是否使用共享鎖,一些不支持共享鎖的操作系統(tǒng),將自動(dòng)將共享鎖改成排它鎖。可以通過(guò)調(diào)用isShared()方法來(lái)檢測(cè)獲得的是什么類(lèi)型的鎖。
(3) lock()和tryLock()的區(qū)別:
lock()阻塞的方法,鎖定范圍可以隨著文件的增大而增加。無(wú)參lock()默認(rèn)為獨(dú)占鎖;有參lock(0L, Long.MAX_VALUE, true)為共享鎖。
tryLock()非阻塞,當(dāng)未獲得鎖時(shí),返回null.
(4)FileLock的生命周期:在調(diào)用FileLock.release(),或者Channel.close(),或者JVM關(guān)閉
(5)FileLock是線(xiàn)程安全的
(6)同一進(jìn)程內(nèi),在文件鎖沒(méi)有被釋放之前,不可以再次獲取。即在release()方法調(diào)用前,只能lock()或者tryLock()一次。
FileChannel channel = null;FileLock lock=null;try {RandomAccessFile raf = new RandomAccessFile("data.txt", "rw");channel = raf.getChannel();//獲得鎖方法一:lock(),阻塞的方法,當(dāng)文件鎖不可用時(shí),當(dāng)前進(jìn)程會(huì)被掛起 lock = channel.lock();//無(wú)參lock()為獨(dú)占鎖 //lock = channel.lock(0L, Long.MAX_VALUE, true);//有參lock()為共享鎖,有寫(xiě)操作會(huì)報(bào)異常 //獲得鎖方法二:trylock(),非阻塞的方法,當(dāng)文件鎖不可用時(shí),tryLock()會(huì)得到null值 //do { // lock = channel.tryLock(); //} while (null == lock); } catch (Exception e) {}finally{if (lock!=null) {lock.release();}if (channel!=null) {channel.close();}}?
?八、ServerSocketChannel 服務(wù)器通道
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.阻塞模式//線(xiàn)程處理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);//設(shè)置為非阻塞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()) {//等待連接成功或者做其他的事 }//非阻塞狀態(tài)有可能沒(méi)有寫(xiě)入數(shù)據(jù)就返回了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();//發(fā)送int length = channel.send(buf, new InetSocketAddress("www.baidu.com", 80));//connect通道可以使用write//channel.write(buf); channel.close();} }?
總結(jié)
以上是生活随笔為你收集整理的Java NIO总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 笔记本电脑显示卡怎么查看?
- 下一篇: Java 线程同步总结