Java之NIO

NIO

New IO, 相对于IO基于字节方式读取流中的数据,NIO以块为单位从Channel读写,相对效率更高。

NIO分为File NIO和NetWork NIO。

File NIO

File NIO通过FileChannel读写数据,FileChannel只能通过FileInputStrem/FileOutputStream获取

public FileChannel FileInputStrem:getChannel();
public FileChannel FileOutputStrem:getChannel();

FileChannel定义了通过ByteBuffer读写数据的接口:

//返回读取数据的字节数,-1代表数据结束
public int read(ByteBuffer dst) throws IOException;
public long read(ByteBuffer[] dsts, int offset, int length) throws IOException;
public final long read(ByteBuffer[] dsts) throws IOException;
public abstract long read(ByteBuffer[] dsts, int offset, int length) throws IOException;
//返回写入的数据字节数
public int write(ByteBuffer src) throws IOException;    
public abstract int write(ByteBuffer src, long position) throws IOException;
public final long write(ByteBuffer[] srcs);
public abstract long write(ByteBuffer[] srcs, int offset, int length);

ByteBuffer是对字节块的抽象,内部是一个byte[], 提供了对块进行操作的各种方法。

FileChannel读取数据时,需先定义一个ByteBuffer用于接受数据,同理写数据时也该先将数据写入ByteBuffer.ByteBuffer提供了静态方法分配一个新ByteBuffer.

public static ByteBuffer allocate(int capacity);

//向Buffer存数据,可指定存放位置index,putShort/putInt/putLong/putFloat/putDouble
public ByteBuffer put(byte b);
public ByteBuffer put(byte[] src);
public ByteBuffer putChar(char value);
public ByteBuffer putChar(int index, char value);
.....
//从Buffer获取数据,可指定位置index, getShort/getInt/getLong/getFloat/getDouble
public byte get();
public byte get(int index);
public char getChar();
public char getChar(int index);

//flip方法让buffer处于初始可读状态
public final Buffer flip() {
    limit = position;
    position = 0;
    mark = -1;
    return this;
}

NetWork NIO

NetWork NIO通过SocketChannel读写数据,UDP中直接new SocketChannel绑定到某个SocketAddress,TCP则需要通过ServerSocketChannel监听到某个端口后接受连接产生一个SocketChannel。

SocketChannel同FileChannel一样,实现了ByteChannel接口,提供读写ByteBuffer的方法相同。

ServerSocketChannel通过静态方法open直接获取,ServerSocketChannel通过accept方法接受一个连接,不能进行读写数据:

public static ServerSocketChannel open() throws IOException {
    return SelectorProvider.provider().openServerSocketChannel();
}

一般IO是阻塞操作,这样单线程如果发生IO阻塞就无法处理其他请求,吞吐量较低,异步IO可以让单线程处理多个IO事件,通过在Selector上注册多个异步Channel监听Channel上发生的IO事件,有点类似Linux下的epoll.

Selector静态方法open()新建Selector:

//open新建Selector    
public static Selector open() throws IOException {
    return SelectorProvider.provider().openSelector();
}

//阻塞监听注册的SelectableChannel是否有IO事件发生,如有IO发生,则返回发生IO的Channel个数
public int select() throws IOException;
public int select(long timeout) throws IOException;

//获取发生IO事件的SelectionKey
public Set<SelectionKey> selectedKeys();

//关闭注册的SelectionKey,但Channel本身并不会关闭
public void close() throws IOException;

继承自SelectableChannel接口的类可向Selector注册,SocketChannel/ServerSocketChannel都继承了SelectableChannel,注册前需设置Chennel为非阻塞模式,注册到Selector后返回SelectionKey即代表了注册的Channel,通过SelectorKey可获取Channel上发生的事件。

public SelectableChannel configureBlocking(boolean block) throws IOException;

public  SelectionKey register(Selector sel, int ops, Object att) throws ClosedChannelException;

public SelectionKey register(Selector sel, int ops) throws ClosedChannelException;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值