Java NIO系列(一) - 概述

前言

Java NIO全称java non-blocking IO,是指jdk1.4及以上版本里提供的新api(New IO),为所有的原始类型(boolean类型除外)提供缓存支持数据容器,使用它可以提供非阻塞式高伸缩性网络

Java NIO提供了与标准IO不同的IO工作方式,ChannelBufferSelector构成了核心的API。其它组件,如PipeFileLock,只不过是与三个核心组件共同使用的工具类

  • 通道和缓冲区 (Channel and Buffer):

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

  • 异步IO (Asynchronous IO):

Java NIO可以让你异步的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情;当数据被线程写入缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。

  • 选择器 (Selector):

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

下面就来详细介绍Java NIO的相关知识。

正文

1. Java NIO概述

Java NIO由以下几个核心部分组成:

  • Channel
  • Buffer
  • Selector

1.1. Channel和Buffer

基本上,所有的IO NIO中都从一个Channel`开始:

通道Channel有点像(Stream),两者可以做个简单对比:

  • 流是单向的,一个流对象要么是输出流、要么是输入流
  • 通道是全双工的,一个通道通常搭配缓存一起使用。数据可以从Channel读到Buffer中,也可以从Buffer写到Channel中。

这里有个图示:

Channel和Buffer`有好几种类型。

JAVA NIO中的一些主要Channel的实现,主要涵盖了文件IOUDPTCP的网络IO

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

JAVA NIO中关键的Buffer实现,涵盖了除boolean的其余7基本数据类型(byteshortintlongfloatdouble 和 char):

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

1.2. Selector

Selector允许单线程处理多个Channel连接事件数据读写。如果你的应用打开了多个连接通道),但每个连接的流量都很低,使用Selector就会很方便,例如:一个聊天服务器。

这是在一个单线程中使用一个Selector处理3Channel的图示:

要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件。

事件类型主要包括:新连接进来、数据接收、数据发送等。

2. Java NIO对比IO

上面提到了NIO主要的组件和特性,在实际的IO操作中,应该如何在标准IONIO进行选择,这里就需要具体对比两者的差异,并引入一些概念。

  IO NIO
底层读写实现 面向流读写 面向缓冲区读写
是否有选择器 基于选择器的事件分离
IO是否阻塞 阻塞式IO 非阻塞式IO

2.1. 底层读写实现

Java NIOIO之间第一个最大的区别是,IO面向流的,NIO面向缓冲区的。

  • 面向流

Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。

  • 面向缓冲区

Java NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。

2.2. 是否有选择器

Java NIO选择器允许一个单独的线程来监视多个输入通道

IO的读写速度和CPU的处理速度相差了一个数量级,导致IO事件延长了CPU的空闲等待时间,导致性能上的瓶颈。为了尽量的缩短CPU的等待时间,在单个IO操作进行时CPU可以抽出身来去做别的事情(其他IO),NIO引入单线程处理多IO事件的概念,从而充分利用CPU分配的资源。

Java NIO允许已注册的多个通道使用一个选择器,然后使用一个单独的线程来选择通道。这种选择机制,使得一个单线程很容易地管理多个通道

2.3. IO是否阻塞

所谓阻塞,就是线程在进行IO操作时,不能抽出身来去干其他事情,必须等待数据读写完成。

  • Java IO的各种流是阻塞的

    • 当一个线程调用read()write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情。
  • Java NIO非阻塞的
    • 当监听某个通道的读操作事件时,线程向该通道发送请求读取数据,之后这个线程就可以去干别的事情。
    • 当监听某个通道的写操作事件时,线程向请求向该通道写入数据,但不需要等待它完全写入,这个线程同时可以去做别的事情。

    线程通常将非阻塞IO空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入输出通道(channel)。



欢迎关注技术公众号: 零壹技术栈

零壹技术栈

本帐号将持续分享后端技术干货,包括虚拟机基础,多线程编程,高性能框架,异步、缓存和消息中间件,分布式和微服务,架构学习和进阶等学习资料和文章。

原文地址:https://www.cnblogs.com/ostenant/p/9695172.html

时间: 2024-11-07 06:15:29

Java NIO系列(一) - 概述的相关文章

java NIO系列教程1

ava NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式. Java NIO: Channels and Buffers(通道和缓冲区) 标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中. Java NIO: Asynchronous IO(异步IO) Java NIO可以让你

Java NIO系列教程(三) Buffer

原文链接:http://ifeve.com/buffers/ 声明:Java NIO系列教材并非本人原创,只因阅读原文之后有感于文章之精妙,意欲与诸位共享,故而出此下策,忘原作者见谅.另附上原文地址. Java NIO的通道类似流,但又有些不同: Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的. 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问

Java NIO系列教程(二) Channel

原文地址:http://ifeve.com/channels/ 声明:Java NIO系列教材并非本人原创,只因阅读原文之后有感于文章之精妙,意欲与诸位共享,故而出此下策,忘原作者见谅.另附上原文地址. Java NIO的通道类似流,但又有些不同: 既可以从通道中读取数据,又可以写数据到通道.但流的读写通常是单向的. 通道可以异步地读写. 通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入. 正如上面所说,从通道读取数据到缓冲区,从缓冲区写入数据到通道.如下图所示: C

java NIO系列教程2

7.FileChannel Java NIO中的FileChannel是一个连接到文件的通道.可以通过文件通道读写文件. FileChannel无法设置为非阻塞模式,它总是运行在阻塞模式下. 打开FileChannel 在使用FileChannel之前,必须先打开它.但是,我们无法直接打开一个FileChannel,需要通过使用一个InputStream.OutputStream或RandomAccessFile来获取一个FileChannel实例.下面是通过RandomAccessFile打开

Java NIO系列教程(五) 通道之间的数据传输

原文地址:http://tutorials.jenkov.com/java-nio/scatter-gather.html 作者:Jakob Jenkov   译者:郭蕾     校对:周泰 在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel(译者注:channel中文常译作通道)传输到另外一个channel. transferFrom() FileChannel的transferFrom()方法可以将数据从源通道传输到FileChanne

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

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

Java NIO 系列教程(转)

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

Java NIO 系列教程

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

Java NIO 系列教程 <转>

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