NIO

Java Nio由以下几个核心部分组成
channels
channel分为有几种类型
FileChannel
DatagramChannel
SocketChannel
ServerSocketChannel

buffers
betyBuffer
CharBuffer
DoubleBuffer
IntBuffer
LongBuffer
ShortBuffer
Selectors
selector允许多个单线程处理多个Channel

Channel

通道 类似流 既可以从通道中读取数据 又可以写数据到通道中 但是流的读写是单向的
通道可以异步的读写
通道中的数据总是要先读到一个buffer 或者总是要从一个Buffer中写入

RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();

Buffer

步骤
写数据到buffer 写的时候 buffer会记录写下了多少数据
调用flip()方法 当要读取数据的时候 需要通过flip()方法将buffer从写模式 切换到读模式
从buffer中读取数据
调用clear()方法 或者compact方法 clear()方法 会清空整个缓冲区 compact方法 只会清除已经读过的数据 任何未读过的数据都被移到缓冲区的起始处 新写入的数据将放到缓冲区未读缓冲区数据 的后面

RandomAccessFile aFile=new RandomAccessFile("XXXXX","rw");
FileChannel inClannel=aFile.getChannel();
ByteBuffer buf=ByteBuffer.allocate(48);//声明缓冲区的容量 
int  byteRead=inChannel.read(buf);
while(byteRead!=-1){
buf.flip();//将buffer从写模式切换为读模式 
while(buf.hasRemaining()){
System.out.print((char)buf.get());
}
buf.clear();
byteRead=inChannel.read(buf);
}
aFile.close();

缓存区的本质上是一块可以写入内存 然后可以从中读取数据的内存 这块内存被包装为NIo Buffer对象 并提供了一组方法 用来方便的访问该块内存
buffer的三个属性 capacity(buffer的容量 ) position limit
position和limit的含义取决于buffer处在读模式还是写模式 不管Buffer处在什么模式 capacity(buffer中最大能存储的容量)的含义是不变的
position
当写数据到Buffer中的时候 position表示当前的位置 初始的Position的值为0;
当一个数据写入的时候 position 会向前移动到下一个可插入数据的Buffer单元 position最大可为capacity -1
当读取数据的时候 也就是从某个特定的位置读 当将buffer从写模式到读模式的时候 position会被重置为0;当从buffer的position处读取数据时 position向前移动到下一个可读的位置
limit 在写模式下 buffer的limit表示最多能往buffer中写多少数据 写模式下 limit的buffer等于capacity
当切换到读模式 limit表示最多能读多少数据 limit被设置为写模式下的Position
向buffer中写数据 从Channel中写数据 int bytesRead=inChannel.read(buf);
通过Buffer的put方法写到Buffer中 buf.put(127);
从buffer中读数据
从Buffer读取数据到Channel int byteswriteten=inchannel.write(buf);
使用get()方法 从BUffer中读取数据 byte abyte=buf.get();
rewind() 重读
java NIO Scatter|Gather
Scatter 从Channel中读取是指在读文件时将读取的数据写入多个buffer中
Gather 写操作的时候 将多个buffer的数据写入同一个Channel

ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body   = ByteBuffer.allocate(1024);

ByteBuffer[] bufferArray = { header, body };

channel.read(bufferArray);
ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body   = ByteBuffer.allocate(1024);

//write data into buffers

ByteBuffer[] bufferArray = { header, body };

channel.write(bufferArray);

nio中 如果两个通道中有一个是FileChannel 那可以直接将数据从一个channel传输到另一个channel
FileChannel的transferFrom()方法 可以将数据从源通道传输到FileChannel 中
transferTo()方法 将数据从FileChannel传输到其他channel中

selector

Selector是Java NIO中能够检测一到多个nio通道 并且能够知晓通道是否为诸如读写事件做好准备的组件 这样一个单独的线程可以管理多个channel 从而管理多个网络连接
仅用单个线程来处理多个Channels的好处是 只需要更少的线程来处理通道 对于操作系统来说 线程上下文之间切换的开销很大 而且每个线程都要占用系统的一些资源 因此 使用的线程越少越好
通过调用Selector.open()方法创建一个Selector Selector selector=Selector.open()
c向Selector注册通道
为了将Channel和Selector配合使用 必须将channel注册到selector上 通过SelectorChannel,register()方法来实现
channel.configureBlocking (false)
SelectorKey key=channel.register(selector,Selectionkey.OP_READ);
与selector一起使用的时候 Channel必须处于非阻塞状态 fileChannel不能和selector一起使用
register()方法的第二个参数 interest集合 意思在通过Selector监听Channel时对什么事件感兴趣 监听什么事件
SelectionKey.OP_CONNECT 某个channel成功连接到另一个服务器称为:连接就绪
SelectionKey.OP_ACCEPT 一个server socket channel准备好接收新进入的连接称为:接受就绪
SelectionKey.OP_READ 一个有数据可读的通道可以说是读就绪
SelectionKey.OP_WRITE 等待写数据的通道就是写就绪
多个事件可以用位与
int interestSet=selectionKet.OP_READ|Selectionkey.OP_WRITE;
SelectionKey对象
对象中包括
interest集合 你选择感兴趣的集合
ready集合 通道已经准备就绪的操作的集合
Channel集合
Selector集合

Selector selector = Selector.open();
channel.configureBlocking(false);
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
while(true) {
  int readyChannels = selector.select();
  if(readyChannels == 0) continue;
  Set 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();
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值