`
QING____
  • 浏览: 2253441 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

NIO-Channel相关接口详解

 
阅读更多

 

一.Channel相关接口(概述):

NIO中核心的API,它被底层操作封装,提供了数据进行NIO操作的"途径",可以配合Selector实现多路IO复用/非阻塞操作.Channel(通道)表示实体(例如硬件设备,文件,网络socket等)的开放链接.Channel与其实体关联,并具有相同的状态,例如关闭或者开启.Channels可以是异步的(noblocking),可中断的(inerruptable).

Channel接口是最顶级的接口.其子接口列表如下:

  1. ReadableByteChannel:可以将内容读入缓冲区,此接口具有一个read(ByteBuffer bb)方法.
  2. ScatteringByteChannel:继承自ReadableByteChannel,可以讲内容依次读入一个或多个缓存区,此接口有一个方法read(ByteBuffer[] dts).
  3. WritableByteChannel:可以将缓冲区内如写入通道,此接口有一个方法write(ByteBuffer bb).
  4. GatheringByteChannel:继承自WritableByteChannel,可以讲多个缓冲区内容依次写入到通道中.此接口有一个方法write(ByteBuffer[] dts).
  5. ByteChannel:一个综合接口,"字节操作渠道",此接口继承ReadableByteChannel/WritableByteChannel.此接口本身无定义方法.

Channels是一个辅助类,提供了多个基于channel操作的util方法.

FileChannel:文件操作的通道,支持向文件进行读取/写入操作FileLock:对文件或者文件区域进行锁定.

MappedByteBuffer:直接映射缓冲区.FileChannel支持连接到文件通道中读取/写入数据,以及查询文件中指定区域(region)的数据.已经在这个文件或者region上锁定的功能(mapping),获取一个FileLock实例.

而且还提供了将文件数据直接映射到内存的方法,即MappedByteBuffer.目前,FileInputStream/FileOutputStream/RandomAccessFile类添加了getChannel方法.这个方法可以获取底层和文档操作绑定的channel.

 

二.多路复用/非阻塞IO通道(概述):

SelectableChannel: 可被选择的通道,能够被Selector支持,是NIO + selector支持的通道."可被选择通道"继承自InterruputableChannel.即为可中断通道.它也是基于网络NIO channel的父接口.我们熟悉的SocketChannel,ServerSocketChannel,DatagramChannel也是扩展自它.

Pipe.SinkChannel,Pipe.SourceChannel这两个基于"管道模式"的通道,也是SelectableChannel.但是Pipe更加特殊.

Selector即为"选择器",是提供多路复用的"操作事件控制"类.

SelectionKey即为"选择键",是channel与selector建立关联的"凭证"或者说是"channel就绪事件"的持有者.

Pipe:一种特殊的channel,形成单向管道的的两个通道,SourceChannel和SinkChannel.

Selector + SelectableChannel + SelectionKey,三者各司其职,并有效配合,最终支撑了NIO数据通讯...

一个channel需要register到指定的一个Selector,此后就可以在此selector上获得和当前channel有关的就绪事件(即SelectionKey).如果某个通道已准备就绪,则将注册是所返回的key添加到选择器的已选择键集合中(selectedKeySet).为了确定哪个通道已准备好执行哪些操作,那么可以通过检查该键集合和其中的key(通常我们采用遍历的方式).selectionKey持有channel信息.

SelectionKey只是channel就绪状态,它本身并不负责对channel的实际操作,因此需要手动去处理这些事件(忽略或者执行).

三.Channel接口

Channel接口是顶级接口,用于控制I/O操作连接,目前已知的文件IO/网络IO都可以获取.

Channel表示到实体(网络设备,文件,Socket等有IO操作)的程序组件的开放连接.我们认为Channel创建成功后,本身持有IO操作的Input和Output.

Channel接口仅仅实现了Closable接口,即任何通道需要具备"开启"状态,以及需要应用手动关闭.

Channel本身底层仍然基于普通的IO,因此channel在多线程环境中是线程安全的.

注意,在Socket操作中,在多个线程中,同时进行进行数据read/write时,数据的操作顺序可能将不能得到保证.所以如果想确保数据发送/读取数据的顺序性,要么对数据进行队列化,要么对操作队列化.(主要原因是底层InputStream/OutputStream非同步操作的).

 

四.WritableByteChannel:可写字节Channel,此接口提供了向通道写入字节序列的能力.在任意给定时刻,一个可写入通道上只能进行一个写入操作。如果某个线程在通道上发起写入操作,那么在第一个操作完成之前,将阻塞其他所有试图发起另一个写入操作的线程。其他种类的 I/O 操作是否继续与写入操作并发执行则取决于该通道的类型。这一点有别于Socket.WritableByteChannel只有一个方法:

  • public int write(ByteBuffer src) throws Exception:write操作,在NIO中只支持ByteBuffer.此方法将制定的字节序列,写入到channel中.注意在非阻塞模式下,write操作并不保证将src中所有的内容都写入后才返回,此方法返回写入成功的字节数,有可能为0,但总是不大于byteBuffer.remaining().在阻塞模式下,write将所有的字节写入完成后,返回.参见Channels.WritableByteChannelImpl

五.ReadableByteChannel:可读字节Channel,同WritableByteChannel对称.任何时刻,只能有一个read操作在此通道上.如果某个线程在通道上发起读取操作,在此操作完成之前,其他线程对此通道的read操作将会被阻塞.参见Channels.ReadableByteChannelImpl;此接口只有一个方法:

  • public int read(ByteBuffer dst) throws Exceoption:从通道中读取数据到buffer中.返回读取到的字节数,可能为0;读取数据长度最大为buffer.capacity().如果此时通道已经到达流的结尾,则返回-1.在非阻塞模式下,read方法可能读取0个字节也会返回.在阻塞模式下,read方法在则阻塞,在至少读取一个字节后可以返回.

六.ByteChannel:一个相对高层的接口,此接口是一个标记接口,没有定义API方法.此接口继承了WritableByteChannel和ReadableByteChannel.常用的FileChannel和SocketChannel都直接实现了此接口.

七.ScatteringByteChannel:"分散"读取操作,是一个高级接口,支持一个通道中一次read操作的结果"分散"给多个byteBuffer.此接口继承自ReadableByteChannel;此接口增加一个特殊的方法:

  • public long read(ByteBuffer[] dsts) throws IOException:将字节序列依次读入指定的缓冲区数组.此接口终于提供给我一种解决方案:一次read的数据分散到过个buffer,然后在多线程使用.或者将一个相对较大的buffer,以多个较小buffer的方式操作.

八.GatheringByteChannel:"集中"写入操作,是一个高级接口,支持一个通道中一次write操作中,将指定的多个ByteBuffer数据依次写入通道.此接口继承自WritableByteChannel.

此接口新增一个特殊的方法:

  • public long write(ByteBuffer[] srcs) throws Exception:返回写入成功的字节个数,可能为0.在非阻塞模式下,有可能返回0或者其他任意不大于srcs的remaning()之和的数字..在阻塞模式下,只有当所有字节都写入,尚可返回.buffer数组将会被依次写入.

九.InterruptibleChannel:"可中断"通道,即此通道可以被异步关闭和中断.

实现此接口的通道是可被异步关闭的,如果某个线程阻塞于InterruptibleChannel的I/O操作中,另一个线程可以调用该通道的close方法.此时被阻塞的线程将会受到AsynchronousCloseException.实现此接口的通道是可被中断的,如果某个线程阻塞于InterruptibleChannel的I/O操作中,则另一个线程可调用该阻塞线程的interrupt方法.这将导致channel被关闭,已阻塞线程将收到ClosedByInterruptException,并且设置阻塞线程的状态为中断.如果已设置某个线程的中断状态,此后它在通道上调用某个阻塞的I/O操作,则该通道将会被关闭且该线程将立即受到ClosedByInterruptException.此接口没有特殊的方法,只是重新定义了close()方法.

此处描述一下"可中断"通道是如何实现异步关闭和中断响应的:参见AbstractInterruptibleChannel

  1. 对于任何通过channel方式read和write操作(参见Channels.WritableByteChannelImpl,Channels.ReadableByteChannelImpl),都将被同步,在read()方法中,需要对一个Object readLock进行同步,在write()方法中需要对一个Object writeLock进行同步.因此对于一个channel在多线程中read(或者write)将会被序列化.
  2. read或者write操作中,在实际的IO操作之前,都会执行AbstractInterruptibleChannel.begin()方法:此方法做的一件事情,就是向Thread.currentThread()注册一个支持异步回调的interruptor对象,即赋值给Thread中Interruptible blocker属性.实际IO操作完毕之后(例如:outputStream.write()...),read或者write方法中将会调用AbstractInterruptibleChannel.end(boolean)方法:此方法将会首先解除Thread中的blocker(即赋值为null),然后检测channel是否被"中断"(每个channel实例,都有一个interrupted属性),如果是,将抛出ClosedByInterruptException.然后检测,当前Channel是否被关闭(channel中有open属性,默认为true),如果是,抛出AsynchronousCloseException.(即被interrupt之后,将会在blocker执行close方法,所以此后channel将不可用)
  3. 执行channel.close()方法时,将会导致其open属性置为false.因此在AbstractInterruptibleChannel.end()方法中检测open属性时,将会抛出相应的异常.难道这就是异步关闭??????好吧,我们简单的认为,当线程"close"了通道,只有其他线程在read或者write时,将会在此后的某个时间被告知"已关闭".根据"异步"的概念,这也可以被认为"异步"吧.
  4. Thread.interrupt()方法中,会对channel注册的interruptor对象进行检测,如果发现此对象不为null,则触发interruptor执行回调方法.回调方法,主要是讲此channel的interrupt属性改为true,open改为false.此后再次channel上调用read或者write时将会触发对interrupt和open属性的校验,以抛出异常.
  5. begin()方法中,仍然会对Thread.currentThead().isInterrupted()校验,如果当前线程已经被"中断",则直接抛出异常..
  6. 经上所述,一个channel的中断和关闭,与Thread控制,形成了密切的回环控制.
  7. 支持noblocking的NIO Channel都实现了此接口.例如SocketChannel,ServerSocketChannel,DatagramChannel,Pipe.SinkChannel,Pipe.SourceChannel等.
分享到:
评论

相关推荐

    Java NIO实战开发多人聊天室

    05-Java NIO-Channel-FileChannel详解(一).mp4 06-Java NIO-Channel-FileChannel详解(二).mp4 08-Java NIO-Channel-ServerSocketChannel.mp4 09-Java NIO-Channel-SocketChannel.mp4 10-Java NIO-Channel-...

    java网络编程NIO视频教程

    Java NIO-Channel-FileChannel详解(一) - **主要内容**:深入探讨FileChannel的高级用法,如文件锁定等。 - **学习目标**:掌握FileChannel的进阶功能。 #### 6. Java NIO-Channel-FileChannel详解(二) - **主要...

    Java-NIO-系列教程

    ### Java NIO 系列教程知识点详解 #### 一、Java NIO 概述 Java NIO (New IO) 是 Java SE 1.4 版本引入的一种新的输入/输出方式,它提供了一种替代传统的 Java IO 包的方式。Java NIO 主要包括三个核心组成部分:*...

    bio-nio-aio.zip

    《Java IO:从NIO到Reactor三种模式详解》 在Java编程中,IO操作是不可或缺的一部分,尤其在处理大量数据传输或者网络通信时。本文将深入探讨Java中的三种IO模型:传统IO(BIO)、非阻塞IO(NIO)以及反应器模式...

    JAVA IO-NIO 详解

    ### JAVA IO-NIO 详解 #### 一、IO与NIO概述 在Java开发中,输入/输出(IO)操作是程序与外部环境交互的重要环节。通过IO操作,程序可以读取外部数据或向外部环境输出数据。Java的IO体系自Java 1.0以来就一直存在...

    JavaNIO_API帮助文档详解

    ### Java NIO_API详解:构建高性能I/O操作的基石 #### 概述 在Java的早期版本中,I/O操作主要依赖于`java.io`包提供的流式、同步的API,这种模型对于多数应用场景而言已经足够高效且易于使用。然而,随着对性能...

    Java NIO详解及源码下载

    Java NIO(New IO)是Java 1.4版本引入的一个新模块,全称为Non-blocking Input/Output,它提供了一种不同于传统IO的编程模型,传统IO基于块I/O(Blocking I/O),而NIO则基于通道(Channels)和缓冲区(Buffers)...

    NIO详细介绍channle,buffer,Selector

    ### NIO:Channel、Buffer与Selector详解 #### 一、NIO概述 NIO(Non-blocking I/O,非阻塞I/O)是Java为了解决传统阻塞式I/O效率低下的问题而引入的一种新的I/O操作模式。NIO通过引入Channel、Buffer以及Selector...

    Java-NIO2教程

    ### Java-NIO2教程知识点详解 #### I/O发展简史 - **JDK1.0-1.3**: 在此期间,Java的I/O模型主要依赖于传统的阻塞I/O方式,这种模式下,应用程序在等待I/O操作完成时无法执行其他任务,导致效率低下。此外,当时的...

    Java_NIO_API详解

    ### Java NIO API详解 #### 一、引言 在Java早期版本中,I/O操作主要依赖于`java.io`包中的流式API,这些API虽然简单易用,但其本质是阻塞式的,这意味着每次读写操作都会等待直至完成。这种机制在处理大量并发...

    JAVA-NIO之Socket/ServerSocket Channel(详解)

    "JAVA-NIO之Socket/ServerSocket Channel详解" JAVA-NIO中有两个重要的Channel:ServerSocketChannel和SocketChannel。下面我们将详细介绍这两个Channel的使用和应用。 一、ServerSocketChannel ...

    详解java NIO之Channel(通道)

    Java NIO 中的 Channel(通道) Channel(通道)是 Java NIO 中的一种 fundamental component,它提供了对 I/O 服务的直接连接,允许开发者高效地传输数据 zwischen 字节缓冲区和位于通道另一侧的实体(通常是一个...

    java.nio API详解

    2. `java.nio.channels`:这个包包含一系列Channel接口和它们的实现,如FileChannel、SocketChannel等。Channel代表了一个开放的I/O资源,数据可以通过Channel进行传输。Selector是这个包中的另一个重要组件,它允许...

    javaNIO很好的资料

    ### Java NIO 相关知识点详解 #### Java NIO 概述 Java NIO(New IO)是从 Java 1.4 版本开始引入的一种新的 I/O 处理方式,它提供了一种不同于传统 Java IO 的操作模式。NIO 的核心组件包括 Channel(通道)、...

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

    - **Buffers**:Buffers是NIO中的数据容器,用于存储从Channel读取的数据或将数据写入Channel。Java NIO支持多种类型的Buffer,包括: - **ByteBuffer**:用于存储字节数据。 - **CharBuffer**:用于存储字符数据...

    java IO、NIO、AIO详解.docx

    Java IO、NIO、AIO 详解 Java IO、NIO、AIO 是 Java 语言中三种不同的输入/输出机制,分别对应着不同的编程模型和设计理念。在高并发环境中,选择合适的输入/输出机制非常重要,本文将对 Java IO、NIO、AIO 进行...

    javaNiO.doc

    ### Java NIO (New IO) 详解 #### 1. 引言 在Java的世界里,I/O(Input/Output)操作是程序与外部环境进行交互的重要方式之一。随着技术的发展,传统I/O模型逐渐显露出一些局限性,特别是在处理高并发场景下,其...

    nio入门 IBM教材,pdf格式

    ### NIO 入门知识点详解 #### 一、NIO 的引入及其背景 - **NIO 的起源**:NIO(New Input/Output)库是在 JDK 1.4 中引入的,旨在解决传统 Java I/O 操作的局限性和性能瓶颈。 - **改进目标**:NIO 通过提供高速...

    java nio 包读取超大数据文件

    ### Java NIO 处理超大数据文件的知识点详解 #### 一、Java NIO简介 Java NIO(New IO)是Java平台上的新输入/输出流API,它提供了与传统IO(即Java IO)不同的数据处理方式。NIO在Java 1.4版本引入,并在后续版本...

Global site tag (gtag.js) - Google Analytics