当前位置: 移动技术网 > IT编程>开发语言>Java > Java NIO:NIO概述

Java NIO:NIO概述

2020年04月01日  | 移动技术网IT编程  | 我要评论

以下是本文的目录大纲:

  一.nio中的几个基础概念

  二.channel

  三.buffer

  四.selector

  若有不正之处,请多多谅解并欢迎批评指正。

  请尊重作者劳动成果,转载请标明原文链接:

   http://www.cnblogs.com/dolphin0520/p/3919162.html

 

 一.nio中的几个基础概念(转载 http://www.cnblogs.com/dolphin0520/p/3919162.html)

 在nio中有几个比较关键的概念:channel(通道),buffer(缓冲区),selector(选择器)。

  首先从channel说起吧,通道,顾名思义,就是通向什么的道路,为某个提供了渠道。在传统io中,我们要读取一个文件中的内容,通常是像下面这样读取的:

1 public class test {
2     public static void main(string[] args) throws ioexception  {
3         file file = new file("data.txt");
4         inputstream inputstream = new fileinputstream(file);
5         byte[] bytes = new byte[1024];
6         inputstream.read(bytes);
7         inputstream.close();
8     }  
9 }

 这里的inputstream实际上就是为读取文件提供一个通道的。

  因此可以将nio 中的channel同传统io中的stream来类比,但是要注意,传统io中,stream是单向的,比如inputstream只能进行读取操作,outputstream只能进行写操作。而channel是双向的,既可用来进行读操作,又可用来进行写操作。

buffer(缓冲区),是nio中非常重要的一个东西,在nio中所有数据的读和写都离不开buffer。比如上面的一段代码中,读取的数据时放在byte数组当中,而在nio中,读取的数据只能放在buffer中。同样地,写入数据也是先写入到buffer中。

下面介绍一下nio中最核心的一个东西:selector。可以说它是nio中最关键的一个部分,selector的作用就是用来轮询每个注册的channel,一旦发现channel有注册的事件发生,便获取事件然后进行处理。

比如看下面的这个例子:

用单线程处理一个selector,然后通过selector.select()方法来获取到达事件,在获取了到达事件之后,就可以逐个地对这些事件进行响应处理。

二.channel

  在前面已经提到,channel和传统io中的stream很相似。虽然很相似,但是有很大的区别,主要区别为:通道是双向的,通过一个channel既可以进行读,也可以进行写;而stream只能进行单向操作,通过一个stream只能进行读或者写;

  以下是常用的几种通道:

  • filechannel
  • socketchanel
  • serversocketchannel
  • datagramchannel

  通过使用filechannel可以从文件读或者向文件写入数据;通过socketchannel,以tcp来向网络连接的两端读写数据;通过serversocketchanel能够监听客户端发起的tcp连接,并为每个tcp连接创建一个新的socketchannel来进行数据读写;通过datagramchannel,以udp协议来向网络连接的两端读写数据。

  下面给出通过filechannel来向文件中写入数据的一个例子:

public class test {
    public static void main(string[] args) throws ioexception  {
        file file = new file("data.txt");
        fileoutputstream outputstream = new fileoutputstream(file);
        filechannel channel = outputstream.getchannel();
        bytebuffer buffer = bytebuffer.allocate(1024);
        string string = "java nio";
        buffer.put(string.getbytes());
        buffer.flip();     //此处必须要调用buffer的flip方法
        channel.write(buffer);
        channel.close();
        outputstream.close();
    }  
}

通过上面的程序会向工程目录下的data.txt文件写入字符串"java nio",注意在调用channel的write方法之前必须调用buffer的flip方法,否则无法正确写入内容

三.buffer

buffer,故名思意,缓冲区,实际上是一个容器,是一个连续数组。channel提供从文件、网络读取数据的渠道,但是读取或写入的数据都必须经由buffer。具体看下面这张图就理解了:

 上面的图描述了从一个客户端向服务端发送数据,然后服务端接收数据的过程。客户端发送数据时,必须先将数据存入buffer中,然后将buffer中的内容写入通道。服务端这边接收数据必须通过channel将数据读入到buffer中,然后再从buffer中取出数据来处理。

  在nio中,buffer是一个顶层父类,它是一个抽象类,常用的buffer的子类有:

  • bytebuffer
  • intbuffer
  • charbuffer
  • longbuffer
  • doublebuffer
  • floatbuffer
  • shortbuffer

  如果是对于文件读写,上面几种buffer都可能会用到。但是对于网络读写来说,用的最多的是bytebuffer。

四.selector

selector类是nio的核心类,selector能够检测多个注册的通道上是否有事件发生,如果有事件发生,便获取事件然后针对每个事件进行相应的响应处理。这样一来,只是用一个单线程就可以管理多个通道,也就是管理多个连接。这样使得只有在连接真正有读写事件发生时,才会调用函数来进行读写,就大大地减少了系统开销,并且不必为每个连接都创建一个线程,不用去维护多个线程,并且避免了多线程之间的上下文切换导致的开销。

  与selector有关的一个关键类是selectionkey,一个selectionkey表示一个到达的事件,这2个类构成了服务端处理业务的关键逻辑。

参考资料:

  

  

  

  

  

作者:

    

出处:

    

本博客中未标明转载的文章归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网