技术开发 频道

JDK 7探秘四:下一代I/O(NIO.2)

  异步I/O

  JSR 51引入了多路复用I/O(无阻塞I/O和选择就绪的结合)使创建高可扩展服务器变得更加容易,本质上是这样的,客户端代码用一个选择器注册一个套接字通道,当通道准备好可以开始I/O操作时发出通知。

  如果要深入研究多路复用I/O,请阅读Ron Hitchens的《Java NIO》一书。

  JSR 203还引入了异步I/O,它也被用来建立高可扩展服务器,和多路复用I/O不同,异步I/O是让客户端启动一个I/O操作,当操作完成后向客户端发送一个通知。

  异步I/O是通过以下位于java.nio.channels包中的接口和类实现的,它们的名称前面都加了Asynchronous前缀:

  · AsynchronousChannel – 标识一个支持异步I/O的通道。

  · AsynchronousByteChannel – 标识一个支持读写字节的异步通道,这个接口扩展了AsynchronousChannel。

  · AsynchronousDatagramChannel – 标识一个面向数据报套接字异步通道,这个类实现了AsynchronousByteChannel。

  · AsynchronousFileChannel – 标识一个可读,写和操作文件的异步通道,这个类实现了AsynchronousChannel。

  · AsynchronousServerSocketChannel – 标识一个面向流监听套接字的异步通道,这个类实现了AsynchronousChannel。

  · AsynchronousSocketChannel – 标识一个面向流连接套接字的异步通道,这个类实现了AsynchronousByteChannel。

  · AsynchronousChannelGroup – 标识一个用于资源共享的异步通道组。

  AsynchronousChannel文档指定了两种形式的异步I/O操作:

  · Future operation(...)

  · void operation(... A attachment, CompletionHandler handler)

  operation列举I/O操作(如读,写),V是操作的结果类型,A是附加给操作的对象类型。

  第一种形式需要你调用java.util.concurrent.Future方法检查操作是否完成,等待完成和检索结果,清单2的代码演示了这样一个示例。

  清单2. AFCDemo1.java

// AFCDemo1.java
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.Future;
public class AFCDemo1
{
  
public static void main (String [] args) throws Exception
   {
      
if (args.length != 1)
      {
          System.err.println (
"usage: java AFCDemo1 path");
          
return;
      }
      Path path
= Paths.get (args [0]);
      AsynchronousFileChannel ch
= AsynchronousFileChannel.open (path);
      ByteBuffer buf
= ByteBuffer.allocate (1024);
      Future
<Integer> result = ch.read (buf, 0);
      
while (!result.isDone ())
      {
         System.out.println (
"Sleeping...");
         Thread.sleep (
500);
      }
      System.out.println (
"Finished = "+result.isDone ());
      System.out.println (
"Bytes read = "+result.get ());
      ch.close ();
   }
}

  调用AsynchronousFileChannel's public static AsynchronousFileChannel open(Path file, OpenOption... options)方法打开file参数进行读取,然后创建了一个字节缓冲区存储读取操作的结果。

  接下来调用public abstract Future read(ByteBuffer dst, long position)方法异步读取文件的前1024个字节,这个方法返回一个Future实例代表这个操作的结果。

  调用read()方法后,进入一个表决循环,重复调用Future的isDone()方法检查操作是否完成,一直等到读操作结束,最后调用Future的get()方法返回读取到的字节大小。

  第二种形式需要你指定java.nio.channels.CompletionHandler,并实现下面的方法使用前面操作返回的结果,或是了解操作为什么失败,并采取适当的行动:

  · 当操作完成时调用void completed(V result, A attachment),这个操作的结果是由result标识的,附加给操作的对象是由attachment标识的。

  · 当操作失败时调用void failed(Throwable exc, A attachment),操作失败的原因是由exc标识的,附加给操作的对象是由attachment标识的。

0
相关文章