Java NIO连串(一):初识NIO

作者: 编程应用  发布:2019-09-26

初识

以下内容整理自互联网,仅用于个人学习

工作中有些地方用到了nettynetty是一个NIO框架,对于NIO却不是那么熟悉,这个系列的文章是我在学习NIO时的一个记录,也期待自己可以更好的掌握NIO


一、NIO是什么?

NIO介绍

NIO是非阻塞的IO,主要由三个核心部分组成:

  • Channels
  • Buffers
  • Selectors

标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入通道也类似。

Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。

Channel和Buffer
基本上,所有的IO和NIO都从一个Channel开始。Channel有点像流。数据可以从Channel读到Buffer中,也可以从Buffer写到Channel中。

Java NIO的通道类似流,但又有些不同:

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

Channel主要有:

  • FileChannel 从文件中读取数据
  • DatagramChannel 能通过UDP读写网络中的数据
  • SocketChannel 能通过TCP读写网络中的数据
  • ServerSocketChannel 可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个

这些通道涵盖了UDP和TCP网络IO,以及文件IO。

Buffer主要有:

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

这些Buffer覆盖了你能通过IO发送的基本数据类型:byte,short,int,long,float,double和char。

Selector
Selector允许单线程处理多个Channel。如果你的应用打开了多个连接(通道),但每一个连接的流量都很低,使用Selector就会很方便。
例如,在一个聊天服务器中,要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件可以是新连接进来,数据接送等。

非阻塞式IO,与传统的BIO不同,NIO可以通过通道来监听各通道的动作,一个线程就可以完成对多个通道的动作监听,这些动作包括连接就绪、写就绪、读就绪等,举个例子,建立连接这个动作在BIO中会发生阻塞,直到连接建立完成,而在NIO中,建连只是单线程里Selector监听的一个动作,也就是说在建立连接之前,这个线程是可以继续处理其他动作的。没有传统IO在IO交互时的阻塞现象,仅通过一个线程来处理n多IO通道,大大提升了程序的处理能力。

NIO的使用

注册:

//创建Selector对象
Selector sel = Selector.open();
//创建可选择通道,并配置为非阻塞模式
ServerSocketChannel server = ServerSocketChannel.open();
server.configureBlocking(false);

//绑定通道到指定端口
ServerSocket socket = server.socket();
InetSocketAddress address = new InetSocketAddress(port);
socket.bind(address);

//向Selector中注册感兴趣的事件
server.register(sel,SelectionKey.OP_ACCEPT);
return sel;

处理:

try{
  while(true){
//该调用会阻塞,直到至少有一个事件发生
    selector.select();
    Set<SelectionKey> keys = selector.selectedKeys();
    Iterator<SelectionKey> iter =       keys.iterator();
    while(iter.hasNext()){
      SelectionKey key = (SelectionKey)iter.next();
      iter.remove();
      process(key);
    }
  }
}catch(IOExceptione){
  e.printStackTrace();
}

二、NIO核心组成部分

1.Channels & Buffer

这两个放在一起讲,Channel是指各种IO通道(包括File、Socket等),也可以理解为双向IO流,即:Channel既可以将自己的内容读到Buffer中,也可以从Buffer中读取数据写入到自己里面。其次,Channel并不一定是双向的,一个Channel如果实现定义read方法的 ReadableByteChannel 接口,而另一个 Channel 类也许实现 WritableByteChannel 接口以提供 write方法。实现这两种接口其中之一的类都是单向的,只能在单个方向上传输数据。如果一个类同时实现这两个接口,那么它是双向的,可以双向传输数据。

结合上面描述,Buffer是一个容器,负责存储从Channel里读到的数据或者存储准备写入Channel的数据,属于一个缓冲区。

常见的Channel:

FileChannel:文件通道

DatagramChannel:一个能收发UDP包的通道。因为UDP是无连接的网络协议,所以不能像其它通道那样读取和写入。它发送和接收的是数据包

SocketChannel:一个连接到TCP网络套接字的通道

ServerSocketChannel:一个可以监听新进来的TCP连接的通道

常见的Buffer:

ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer

可以发现,涵盖了基本传输的数据类型。

2.Selector

可以理解为“Channel事件选择处理器”,第一部分有提到说NIO属于非阻塞式IO,关键点在于Selector可以运行于一个单线程里,然后通过一个死循环来监听注册到选择器内的Channel的事件(注意这里,一个Channel的事件想要被选择器监听到,则要求该Channel必须注册到选择器里),这些事件上面也提到过包含:连接就绪、写就绪、读就绪等。这些动作全部由Channel自己完成,什么时候完成了通知选择器去进行相应的逻辑处理即可,而不必阻塞在IO交互上(也是与传统BIO不同的点),选择器工作如下图:

图片 1

本篇简单介绍了下NIO,接下来将会介绍具体如何去使用

本文由金沙澳门官网送注册58发布于编程应用,转载请注明出处:Java NIO连串(一):初识NIO

关键词:

上一篇:strcpy()的实现
下一篇:分页突显数据