文档章节

Java NIO:NIO概述

谢谢小哥
 谢谢小哥
发布于 2017/09/11 13:26
字数 1341
阅读 10
收藏 1

以下是本文的目录大纲:

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

© 著作权归作者所有

共有 人打赏支持
谢谢小哥
粉丝 2
博文 27
码字总数 50223
作品 0
沈阳
程序员
Java NIO系列教程(一) Java NIO 概述

Java NIO 由以下几个核心部分组成: Channels Buffers Selectors 虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Channel,Buffer 和 Selector 构成了核心的API。其它组件,如Pipe和...

只想一个人静一静
2014/02/22
0
0
分别使用Java IO、NIO、Netty实现的一个Echo Server示例

分别使用Java IO、Java NIO、Netty来实现一个简单的EchoServer(即原样返回客户端的输入信息)。 Java IO int port = 9000;ServerSocket ss = new ServerSocket(port);while (true) {final S...

zgw06629
2015/05/24
0
0
Java NIO AsynchronousFileChannel

原文链接 , 原文作者:Jakob Jenkov, 翻译:Neil Hao 在Java 7,AsynchronousFileChannel 被添加到了Java NIO中。使用AsynchronousFileChannel可以实现异步地读取和写入文件数据。 创建一个A...

Neil_Hao
01/20
0
0
Java NIO原理 图文分析及代码实现

Java NIO原理图文分析及代码实现 前言: 最近在分析hadoop的RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术...

囚兔
2015/04/29
0
0
Java NIO原理图文分析及代码实现

前言: 最近在分析hadoop的RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。可以参考:http://baik...

SunnyWu
2014/11/05
0
1

没有更多内容

加载失败,请刷新页面

加载更多

python装饰器执行顺序

上来先看代码: import timedef deco(func): def wrapper(): startTime = time.time() print "start" func() print "end" endTime =......

fang_faye
10分钟前
1
0
java常用设计模式

一、创建型 1、工厂方法(Factory Method) a、普通工厂:根据不同参数返回创建的不同对象。 b、工厂方法:根据不同方法返回创建的不同对象。 c、静态工厂:将方法改为static类型。 场景:S...

狠一点
12分钟前
1
0
python:获取文件最后N行

#获取文件最后N行的函数 def tail(inputfile) : filesize = os.path.getsize(inputfile) blocksize = 1024 dat_file = open(inputfile, 'r') last_line = "" if filesize > blocksize : maxs......

perofu
18分钟前
2
0
JavaScript(四):注释

认识 注释的作用 是提高代码的可读性,帮助自己和别人阅读和理解你所编写的JavaScript代码,注释的内容不会在网页中显示。 注释可分为 单行注释与 多行注释 两种。 我们为了方便阅读,注释内...

Agnes2017
25分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部