Java NIO (1)

Java NIO (1)

看了下java核心技术这本书 关于nio的部分介绍比较少,而且如果自己写服务器的话nio用的还是比较多,整理一下nio的资料

java中nio主要是三个组件

  • Buffers
  • Channels
  • Selectors

Buffer可以理解为缓冲区,NIO中的Buffer实现很多,一般常用的就是ByteBuffer

ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
ByteBuffer mapedBuffer = ByteBuffer.allocateDirect(1024);

一般情况下我们不必直接操作byteBuffer,都是用一个Channel来操作

FileChannel fileChannel = FileChannel.open(path);
int hadread = fileChannel.read(byteBuffer);

调用flip切换为读写模式

int hadread;
while ((hadread=fileChannel.read(byteBuffer))>0){
	byteBuffer.flip();
	byte[] bytes = new byte[1024];
	System.out.println(hadread);
	byteBuffer.get(bytes,0,hadread);
	for (int i = 0; i < hadread; i++) {
		System.out.println(bytes[i]);
	}
	byteBuffer.flip();
}

如果遇到了网络编程,我们可能会需要类似于linux select epoll的功能,java nio已经为我们提供了

一般情况下,我们使用单个线程处理多个Channels,因为如果线程过多,可能造成频繁的上下文切换导致开销过高(跟太频繁系统调用一个道理)

selector就为我们提供了这样的功能

不过selector只能跟SocketChannel一起使用,因为Channel必须处于非阻塞模式下

FileChannel没有configureBlocking这个方法

Selector selector = Selector.open();
SocketChannel channel = server.accept();
// 有新的连接并不代表这个通道就有数据,
// 这里将这个新的 SocketChannel 注册到 Selector,监听 OP_READ 事件,等待数据
channel.configureBlocking(false);
//注册给某个selector
SelectionKey key = channel.register(selector,
    Selectionkey.OP_READ);
SelectionKey key;
Channel  channel  = key.channel();
Selector selector = key.selector();

注册完之后,就可以像linux那样select

//调用select
// @return  The number of keys, possibly zero,
// whose ready-operation sets were updated
int readys = selector.select();
//获取就绪事件的集合
Set selectedKeys = selector.selectedKeys();

//这里返回的是所有就绪事件,比如说可以读,可以写,可以连接

//完整实例:

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();
  }
}

这个网站里面nio写的很好

http://ifeve.com/overview/

还有这个

http://www.importnew.com/28021.html

原文地址:https://www.cnblogs.com/stdpain/p/10665338.html