NIO概述

现在我们开始进入Java NIO编程主题。NIO是Java 4里面提供的新的API,目的是用来解决传统IO的问题。本文下面分别从Java NIO的几个基础概念介绍起。

  以下是本文的目录大纲:

  一.NIO中的几个基础概念

  二.Channel

  三.Buffer

  四.Selector

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

  

一.NIO中的几个基础概念

  在NIO中有几个比较关键的概念:Channel(通道),Buffer(缓冲区),Selector(选择器)。

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


1

2

3

4

5

6

7

8

9

public class Test {

    public static void main(String[] args) throws IOException  {

        File file = new File("data.txt");

        InputStream inputStream = new FileInputStream(file);

        byte[] bytes = new byte[1024];

        inputStream.read(bytes);

        inputStream.close();

    }  

}

   这里的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来向文件中写入数据的一个例子:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

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

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

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

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

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

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

  关于Buffer的具体使用以及它的limit、posiion和capacity这几个属性的理解在下一篇文章中讲述。

四.Selector

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

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

  关于Selector类的具体使用将在后续文章中阐述。

  参考资料:

  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/

 

五、关于写操作

写就绪相对有一点特殊,一般来说,你不应该注册写事件。写操作的就绪条件为底层缓冲区有空闲空间,而写缓冲区绝大部分时间都是有空闲空间的,所以当你注册写事件后,写操作一直是就绪的,选择处理线程全占用整个CPU资源。所以,只有当你确实有数据要写时再注册写操作,并在写完以后马上取消注册。

 

当有数据在写时,将数据写到缓冲区中,并注册写事件。

 

[java] view plain copy

 

  1. public void write(byte[] data) throws IOException {  
  2.     writeBuffer.put(data);  
  3.     key.interestOps(SelectionKey.OP_WRITE);  
  4. }  

注册写事件后,写操作就绪,这时将之前写入缓冲区的数据写入通道,并取消注册。

 

[java] view plain copy

 

  1. channel.write(writeBuffer);  
  2. key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);  

原文链接:[http://wely.iteye.com/blog/2324806]

 

时间: 2025-01-25 09:12:28

NIO概述的相关文章

Java NIO系列教程(一) Java NIO 概述

原文链接     作者:Jakob Jenkov     译者:airu     校对:丁一 Java NIO 由以下几个核心部分组成: Channels Buffers Selectors 虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Channel,Buffer 和 Selector 构成了核心的API.其它组件,如Pipe和FileLock,只不过是与三个核心组件共同使用的工具类.因此,在概述中我将集中在这三个组件上.其它组件会在单独的章节中讲到. Channel 和 Bu

Java NIO概述

IO与NIO的区别 IO是面向流的,而NIO是面向块(缓冲区)的.面向块的方式中,一次性可以获取或者写入一整块数据,而不需要一个字节一个字节的从流中读取.面向块的方式处理数据的速度会比流方式更快. NIO基础 通道 Channel与缓冲器Buffer Buffer是一个保存数据的地方,包括刚刚写入的数据,以及被读取的数据,主要用来追踪系统的读写进程. Channel与流模式比较类似,但是,永远无法将数据直接写入到Channel或者从Channel中读取数据.需要通过Buffer与Channel交

NIO - 概述

一、   说明 关于IO模型,请参考<IO模型>   说明:文中Java IO或传统IO简称IO.本文是<Netty权威指南>的读书笔记,如果错误,欢迎指出,谢谢   二、   NIO简介 NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区), Selector. 传统IO基于字节流和字符流进行操作,而NIO基于Channel和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中.Selector(选择区

Java NIO 系列教程

Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API.本系列教程将有助于你学习和理解Java NIO.感谢并发编程网的翻译和投递.  (关注ITeye官微,随时随地查看最新开发资讯.技术文章.)  [本文转载于 Java NIO 系列教程] Java NIO提供了与标准IO不同的IO工作方式:  Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channe

Java NIO 系列教程(转)

原文中说了最重要的3个概念,Channel 通道Buffer 缓冲区Selector 选择器其中Channel对应以前的流,Buffer不是什么新东西,Selector是因为nio可以使用异步的非堵塞模式才加入的东西.以前的流总是堵塞的,一个线程只要对它进行操作,其它操作就会被堵塞,也就相当于水管没有阀门,你伸手接水的时候,不管水到了没有,你就都只能耗在接水(流)上.nio的Channel的加入,相当于增加了水龙头(有阀门),虽然一个时刻也只能接一个水管的水,但依赖轮换策略,在水量不大的时候,各

java NIO 详解_java

Java NIO提供了与标准IO不同的IO工作方式: Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中. Asynchronous IO(异步IO):Java NIO可以让你异步的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情.当数据被写入到缓冲区时,线程可以继续处理它.从缓冲区写入通道也类似. S

java的nio之:java的nio系列教程之概述

一:java的nio的核心组件?Java NIO 由以下几个核心部分组成: ==>Channels ==>Buffers ==>Selectors 虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Channel,Buffer 和 Selector 构成了核心的API.其它组件,如Pipe和FileLock,只不过是与三个核心组件共同使用的工具类.因此,在概述中我将集中在这三个组件上.其它组 件会在单独的章节中讲到. Channel 和 Buffer 基本上,所有的 IO 在

gecko框架概述

1 gecko概述 最近在研究metaq消息队列,它里面用到的NIO通信框架是gecko,文档是这么描述的 Gecko是一个Java NIO的通讯组件,它在一个轻量级的NIO框架的基础上提供了更高层次的封装和功能. 支持的RPC调用方式包括RR(request-response)和pipeline. 0 可插拔的协议设计 1 连接池 2 分组管理和负载均衡 3 Failover/Retry 4 重连管理 5 同步和异步调用 本文就按照日常NIO通信框架和RPC所面临的问题来看下gecko是怎么解

java NIO

这次是关于java nio,有一些重复的发的地方.本文中的源代码可以在此处下载,下载链接为:http://115.com/file/cltlj10i#nio-src.zip 本文简介:  JDK 1.4 中引入的新输入输出 (NIO) 库在标准 Java 代码中提供了高速的.面向块的 I/O.本实用教程从高级概念到底层的编程细节,非常详细地介绍了 NIO 库.您将学到诸如缓冲区和通道这样的关键 I/O 元素的知识,并考察更新后的库中的标准 I/O 是如何工作的.您还将了解只能通过 NIO 来完成