1. 概述

在本文中,我们将探讨Java 7中新增的NIO2(New I/O)API之一——异步通道API的基础知识。这将是关于此特定主题的一系列文章的第一篇。

异步通道API是对Java 1.4中随NIO一起发布的早期新IO API的增强。有关NIO选择器的详细信息,请参阅此处

NIO API的另一个增强是新的文件系统API。您也可以在这个网站上了解更多关于其文件操作路径操作的内容。

要在项目中使用NIO2的异步通道,我们需要导入java.nio.channels包,因为所需的类都包含在其中:

import java.nio.channels.*;

2. 异步通道API的工作原理

异步通道API被引入到现有的java.nio.channels包中,简单来说,就是通过在类名前加上“异步”前缀实现的。

一些核心类包括:AsynchronousSocketChannelAsynchronousServerSocketChannelAsynchronousFileChannel

您可能已经注意到,这些类的风格类似于标准的NIO通道API。

而且,大部分可用在NIO通道类上的API操作也适用于新的异步版本。主要的区别在于,新的通道允许某些操作异步执行。

当我们发起一个操作时,异步通道API为我们提供了两种监控和控制待处理操作的方式。操作可以返回java.util.concurrent.Future对象,或者我们可以传递一个java.nio.channels.CompletionHandler

3. Future方法

Future对象表示异步计算的结果。假设我们要创建一个服务器来监听客户端连接,我们会调用AsynchronousServerSocketChannel的静态open方法,并可选地将返回的套接字通道绑定到一个地址:

AsynchronousServerSocketChannel server 
  = AsynchronousServerSocketChannel.open().bind(null);

我们传入null,以便系统自动分配地址。然后,我们在返回的服务器SocketChannel上调用accept方法:

Future<AsynchronousSocketChannel> future = server.accept();

在旧IO中,调用ServerSocketChannelaccept方法会阻塞,直到接收到来自客户端的连接。但是,AsynchronousServerSocketChannelaccept方法会立即返回一个Future对象。

Future对象的通用类型是操作的返回类型。在上述示例中,它是AsynchronousSocketChannel,但根据操作最终的返回类型,它也可能是IntegerString

我们可以使用Future对象查询操作的状态:

future.isDone();

如果操作已完成,这个API会返回true。请注意,此处的完成可能意味着正常终止、异常或取消。

我们还可以显式检查操作是否已被取消:

future.isCancelled();

只有当操作在正常完成之前被取消时,它才会返回true,否则返回false。取消操作由cancel方法执行:

future.cancel(true);

调用此方法会取消由Future对象表示的操作。参数表示即使操作已经开始,也可以中断。一旦操作完成,就无法取消。

要获取计算结果,我们使用get方法:

AsynchronousSocketChannel client= future.get();

如果我们在这之前调用此API,它会阻塞直到完成,然后返回操作的结果。

4. CompletionHandler方法

使用Future处理操作的另一种方法是使用CompletionHandler类的回调机制。异步通道允许指定一个完成处理器来消费操作的结果:

AsynchronousServerSocketChannel listener
  = AsynchronousServerSocketChannel.open().bind(null);

listener.accept(
  attachment, new CompletionHandler<AsynchronousSocketChannel, Object>() {
    public void completed(
      AsynchronousSocketChannel client, Object attachment) {
          // do whatever with client
      }
    public void failed(Throwable exc, Object attachment) {
          // handle failure
      }
  });

当I/O操作成功完成时,completed回调会被调用。如果操作失败,将调用failed回调。

这些回调方法接受其他参数,以允许我们传递任何我们认为适合与操作关联的数据。这个第一个参数作为回调方法的第二个参数提供。

最后,一个明显的场景是——使用同一个CompletionHandler处理不同的异步操作。在这种情况下,我们将在后续部分看到,通过标记每个操作来提供处理结果时的上下文将大有裨益。

5. 总结

在本文中,我们探讨了Java NIO2异步通道API的入门知识。

要获取本文的所有代码片段和完整源代码,请访问GitHub项目


« 上一篇: Java中的排序用法
» 下一篇: NIO2文件属性API指南