zoukankan      html  css  js  c++  java
  • Java NIO:NIO概述

    以下是本文的目录大纲:

      一.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个类构成了服务端处理业务的关键逻辑。

    参考资料:

      http://blog.csdn.net/wuxianglong/article/details/6604817

      http://www.360doc.com/content/12/0515/11/1542811_211144310.shtml

      http://www.iteye.com/topic/834447

      http://weixiaolu.iteye.com/blog/1479656

      http://ifeve.com/overview/

    作者:Matrix海子

        

        

    本博客中未标明转载的文章归作者Matrix海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    软工实践4
    软工实践3
    软工实践1
    《暗时间》读书笔记
    关系规范化(数据库)
    关于Git的初步使用
    软件体系结构模式
    第六周编程总结
    第五周编程总结
    第四周编程总结
  • 原文地址:https://www.cnblogs.com/whwsoft/p/12610489.html
Copyright © 2011-2022 走看看