Java NIO的通道类似流,但又有些不同:

  • 既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。
  • 通道可以异步地读写。
  • 通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。

正如上面所说,从通道读取数据到缓冲区,从缓冲区写入数据到通道。

Channel的实现

这些是Java NIO中最重要的通道的实现:

  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel

FileChannel 从文件中读写数据。

DatagramChannel 能通过UDP读写网络中的数据。

SocketChannel 能通过TCP读写网络中的数据。

ServerSocketChannel可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。

多数情况下,通道与操作系统的文件描述符(File Descriptor)和文件句柄(File Handle)有着一对一的关系(通道比文件描述符更广义)。

Channel接口:

public interface Channel
{
public boolean isOpen( );
public void close( ) throws IOException;
}

  与缓冲区不同,通道API主要由接口指定。不同的操作系统上通道实现(Channel Implementation)会有根本性的差异,所以通道API仅仅描述了可以做什么。因此很自然地,通道实现经常使用操作系统的本地代码。通道接口允许您以一种受控且可移植的方式来访问底层的I/O服务。

InterruptibleChannel接口:

  InterruptibleChannel是一个标记接口,当被通道使用时可以标示该通道是可以中断的(Interruptible)。如果连接可中断通道的线程被中断,那么该通道会以特别的方式工作。

两个对应的核心抽象类:

  这两个类是AbstractInterruptibleChannel和AbstractSelectableChannel,它们分别为可中断的(interruptible)和可选择的(selectable)的通道实现提供所需的常用方法。尽管描述通道行为的接口都是在java.nio.channels包中定义的,不过具体的通道实现却都是从java.nio.channels.spi中的类引申来的。这使得他们可以访问受保护的方法,而这些方法普通的通道用户永远都不会调用。

获取管道的集中常见操作:

ServerSocketChannel ssc = ServerSocketChannel.open( );
ssc.socket( ).bind (new InetSocketAddress (8080)); SocketChannel sc = SocketChannel.open( );
sc.connect (new InetSocketAddress("localhost", 8080)); DatagramChannel dc = DatagramChannel.open( ); RandomAccessFile raf = new RandomAccessFile ("E:\\JcloudMyProject\\blogcode\\src\\main\\java\\heapStark\\blogCode\\nio\\Main.java", "r");
FileChannel fc = raf.getChannel( );
//Socket 无法产生Channel
Socket socket = new Socket();
socket.connect( new InetSocketAddress("localhost",8080));
assert (socket.getChannel()==null);

Socket类也有新的getChannel( )方法。这些方法虽然能返回一个相应的socket通道对象,但它们却并非新通道的来源,RandomAccessFile.getChannel( )方法才是。只有在已经有通道存在的时候,Socket类的getChannel( )方法才返回与一个socket关联的通道否则返回空。

关闭通道:

  与缓冲区不同,通道不能被重复使用。一个打开的通道即代表与一个特定I/O服务的特定连接并封装该连接的状态。当通道关闭时,那个连接会丢失,然后通道将不再连接任何东西。调用通道的close( )方法时,可能会导致在通道关闭底层I/O服务的过程中线程暂时阻塞,哪怕该通道处于非阻塞模式。通道关闭时的阻塞行为(如果有的话)是高度取决于操作系统或者文件系统的。在一个通道上多次调用close( )方法是没有坏处的,但是如果第一个线程在close( )方法中阻塞,那么在它完成关闭通道之前,任何其他调用close( )方法都会阻塞。后续在该已关闭的通道上调用close( )不会产生任何操作,只会立即返回。尝试进行任何需要通道处于开放状态作为前提的操作,如读、写等都会导致ClosedChannelException异常。

ByteChannel继承关系:

  ByteChannel接口本身并不定义新的API方法,它是一种用来聚集它自己以一个新名称继承的多个接口的便捷接口。根据定义,实现ByteChannel接口的通道会同时实现ReadableByteChannel 和WritableByteChannel两个接口,所以此类通道是双向的。这是简化类定义的语法糖(syntactic sugar)。

阻塞(blocking)或非阻塞(nonblocking):

  通道可以以阻塞(blocking)或非阻塞(nonblocking)模式运行。非阻塞模式的通道永远不会让调用的线程休眠。请求的操作要么立即完成,要么返回一个结果表明未进行任何操作。只有面向流的(stream-oriented)的通道,如sockets和pipes才能使用非阻塞模式。SocketChannel通道类从SelectableChannel引申而来。从SelectableChannel引申而来的类可以和支持有条件的选择(readiness selectio)的选择器(Selectors)一起使用。将非阻塞I/O和选择器组合起来可以使您的程序利用多路复用I/O(multiplexed I/O)。

  • InterruptibleChannel接口,标记接口

如果一个线程在一个InterruptibleChannel通道上被阻塞并且同时被中断(由调用该被阻塞线程的interrupt( )方法的另一个线程中断),那么该通道将被关闭,

该被阻塞线程也会产生一个ClosedByInterruptException异常。此外,假如一个线程的interrupt status被设置并且该线程试图访问一个通道,

那么这个通道将立即被关闭,同时将抛出相同的ClosedByInterruptException异常。线程的interrupt status在线程的interrupt( )方法被调用时会被设置。

我们可以使用isInterrupted( )来测试某个线程当前的interrupt status。当前线程的interrupt status可以通过调用静态的Thread.interrupted( )方法清除。

仅仅因为休眠在其上的线程被中断就关闭通道,这看起来似乎过于苛刻了。不过这却是NIO架构师们所做出的明确的设计决定。经验表明,想要在所有的操作系统上一致而可靠地处理被中断的I/O操作是不可能的。“在全部平台上提供确定的通道行为”这一需求导致了“当I/O操作被中断时总是关闭通道”这一设计选择。这个选择被认为是可接受的,因为大部分时候一个线程被中断就是希望以此来关闭通道。java.nio包中强制使用此行为来避免因操作系统独特性而导致的困境,因为该困境对I/O区域而言是极其危险的。这也是为增强健壮性(robustness)而采用的一种经典的权衡。可中断的通道也是可以异步关闭的。实现InterruptibleChannel接口的通道可以在任何时候被关闭,即使有另一个被阻塞的线程在等待该通道上的一个I/O操作完成。当一个通道被关闭时,休眠在该通道上的所有线程都将被唤醒并接收到一个AsynchronousCloseException异常。接着通道就被关闭并将不再可用。

NIO Channel 管道的更多相关文章

  1. Java NIO Channel和Buffer

    Java NIO Channel和Buffer @author ixenos Channel和Buffer的关系 1.NIO速度的提高来自于所使用的结构更接近于OS执行I/O的方式:通道和缓冲器: 2 ...

  2. Java NIO Channel之FileChannel [ 转载 ]

    Java NIO Channel之FileChannel [ 转载 ] @author zachary.guo 对于文件 I/O,最强大之处在于异步 I/O(asynchronous I/O),它允许 ...

  3. Java NIO Channel通道

    原文链接:http://tutorials.jenkov.com/java-nio/channels.html Java NIO Channel通道和流非常相似,主要有以下几点区别: 通道可以读也可以 ...

  4. (三:NIO系列) Java NIO Channel

    出处: Java NIO Channel 1.1. Java NIO Channel的特点 和老的OIO相比,通道和NIO流(非阻塞IO)主要有以下几点区别: (1)OIO流一般来说是单向的(只能读或 ...

  5. NIO Channel Scatter/Gather 管道Pipe类

    通道提供了一种被称为Scatter/Gather的重要新功能(有时也被称为矢量I/O).Scatter/Gather是一个简单却强大的概念,它是指在多个缓冲区上实现一个简单的I/O操作.对于一个wri ...

  6. NIO之管道 (Pipe)

    Java NIO 管道是2个线程之间的单向数据连接.Pipe有一个source通道和一个sink通道.数据会被写到sink通道,从source通道读取. 代码使用示例: public static v ...

  7. [翻译] java NIO Channel

    原文地址:http://tutorials.jenkov.com/java-nio/channels.html JAVA NIO channels和流的概念很像,下面是他们的一些区别: 你可以对cha ...

  8. Java NIO Channel to Channel Transfers通道传输接口

    原文链接:http://tutorials.jenkov.com/java-nio/channel-to-channel-transfers.html 在Java NIO中如果一个channel是Fi ...

  9. NIO Channel和Buffer

    Java NIO 由以下几个核心部分组成: Buffer Channel Selector 传统的IO操作面向数据流,意味着每次从流中读一个或多个字节,直至完成,数据没有被缓存在任何地方.NIO操作面 ...

随机推荐

  1. python day19 : 购物商城作业,进程与多线程

    目录 python day 19 1. 购物商城作业要求 2. 多进程 2.1 简述多进程 2.2 multiprocessing模块,创建多进程程序 2.3 if name=='main'的说明 2 ...

  2. win10 提示该文件没有与之关联的应用来执行该操作

    将下面代码复制进一个文本文档,然后将文本文档的txt后缀改成bat.双击运行,可以解决问题. 问题发生原因是之前通过注册表去除了桌面图标的快捷方式的小标志. /-------------------- ...

  3. Keystore was tampered with, or password was incorrect

    #修改key条目密码 # keytool -keypasswd -alias test.com -keypass oldkeypwd -new newkeypwd -storepass storepw ...

  4. 自动化运维-Ansible-playbook

    Ansible Playbook https://ansible-tran.readthedocs.io/en/latest/docs/playbooks_intro.html Ansible中文网址 ...

  5. 21.centos7基础学习与积累-007-远程连接

    从头开始积累centos7系统运用 大牛博客:https://blog.51cto.com/yangrong/p5 IP地址: 互联网上的计算机 都会有一个唯一的32位的地址,ip地址,我们访问服务器 ...

  6. 如何进行SQL注入攻击?

    1.数字注入 2.字符串注入 3. #后边全部为注释,字符串拼装后绕过密码验证. 4. 同样绕过密码验证

  7. 深层次揭示runBlocking与coroutineScope之间的异同点

    在之前https://www.cnblogs.com/webor2006/p/11731763.html咱们写过这样的一个例子,先来回顾一下: 也就是来演示runBlocking与coroutineS ...

  8. Justice(HDU6557+2018年吉林站+二进制)

    题目链接 传送门 题意 给你\(n\)个数,每个数表示\(\frac{1}{2^{a_i}}\),要你把这\(n\)个数分为两堆,使得每堆的和都大于等于\(\frac{1}{2}\). 思路 首先我们 ...

  9. 用IntelliJ IDEA学习Spring--创建一个简单的项目

    这段时间想学习一下Spring,其实之前学过Spring,只是有些忘记了.而且之前学的时候是适用eclipse学习的,现在好像对IntelliJ这个工具使用挺多的,现在就学习一下这个工具的用法,顺便复 ...

  10. 9、Python复杂数据类型(list、tuple、set、dict)

    一.列表(list):[a1,a2],可变数据类型 1.序列: 序列是基类类型,序列扩展类型包括:字符串.元组和列表 序列都可以进行的操作包括索引,切片,加,乘,检查成员. 此外,Python已经内置 ...