首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

NIO.2 入门 异步通路 API

2012-08-29 
NIO.2 入门异步通道 API异步通道 提供支持连接、读取、以及写入之类非锁定操作的连接,并提供对已启动操作的

NIO.2 入门 异步通道 API
异步通道 提供支持连接、读取、以及写入之类非锁定操作的连接,并提供对已启动操作的控制机制。Java 7 中用于 Java Platform(NIO.2)的 More New I/O APIs,通过在 java.nio.channels 包中增加四个异步通道,从而增强了 Java 1.4 中的 New I/O APIs(NIO):
AsynchronousSocketChannel
AsynchronousServerSocketChannel
AsynchronousFileChannel
AsynchronousDatagramChannel
这些类在风格上与 NIO 通道 API 很相似。他们共享相同的方法与参数结构体,并且大多数对于 NIO 通道类可用的参数,对于新的异步版本仍然可用。主要区别在于新通道可使一些操作异步执行。
异步通道 API 提供两种对已启动异步操作的监测与控制机制。第一种是通过返回一个 java.util.concurrent.Future 对象来实现,它将会建模一个挂起操作,并可用于查询其状态以及获取结果。第二种是通过传递给操作一个新类的对象,java.nio.channels.CompletionHandler,来完成,它会定义在操作完毕后所执行的处理程序方法。每个异步通道类为每个操作定义 API 副本,这样可采用任一机制。

首先,我们将了解 AsynchronousServerSocketChannel 和 AsynchronousSocketChannel 类。我们将看到的第一个例子将演示如何利用这些新的类来实施简单的客户端/服务器。第一步,我们要设置服务器。
设置服务器
打开 AsychronousServerSocketChannel 并将其绑定到类似于 ServerSocketChannel 的地址:



现在可以进行写入:
fileChannel.write(ByteBuffer.wrap(bytes), 0,"Write operation 1", handler);

write() 方法采取:
包含要写入内容的 ByteBuffer
文件中的绝对位置
要传递给完成处理程序方法的附件对象
完成处理程序
操作必须给出进行读或写的文件中的绝对位置。文件具有内部位置标记,来指出读/写发生的位置,这样做没有意义,因为在上一个操作完成之前,就可以启动新操作,它们的发生顺序无法得到保证。由于相同的原因,在 AsynchronousFileChannel API 中没有用于设置或查询位置的方法,在 FileChannel 中同样也没有。
除了读写方法之外,还支持异步锁定方法,因此,如果当前有其他线程保持锁定时,可对文件进行执行访问锁定,而不必在当前线程中锁定(或者利用 tryLock 轮询)。
回页首
异步通道组
每个异步通道都属于一个通道组,它们共享一个 Java 线程池,该线程池用于完成启动的异步 I/O 操作。这看上去有点像欺骗,因为您可在自己的 Java 线程中执行大多数异步功能,来获得相同的表现,并且,您可能希望能够仅仅利用操作系统的异步 I/O 能力,来执行 NIO.2 ,从而获得更优的性能。然而,在有些情况下,有必要使用 Java 线程:比如,保证 completion-handler 方法在来自线程池的线程上执行。
默认情况下,具有 open() 方法的通道属于一个全局通道组,可利用如下系统变量对其进行配置:
java.nio.channels.DefaultThreadPoolthreadFactory,其不采用默认设置,而是定义一个 java.util.concurrent.ThreadFactory
java.nio.channels.DefaultThreadPool.initialSize,指定线程池的初始规模
java.nio.channels.AsynchronousChannelGroup 中的三个实用方法提供了创建新通道组的方法:
withCachedThreadPool()
withFixedThreadPool()
withThreadPool()
这些方法或者对线程池进行定义,如 java.util.concurrent.ExecutorService,或者是 java.util.concurrent.ThreadFactory。例如,以下调用创建了具有线程池的新的通道组,该线程池包含 10 个线程,其中每个都构造为来自 Executors 类的线程工厂:
AsynchronousChannelGroup tenThreadGroup =
    AsynchronousChannelGroup.withFixedThreadPool(10, Executors.defaultThreadFactory());

三个异步网络通道都具有 open() 方法的替代版本,它们采用给出的通道组而不是默认通道组。例如,当有异步操作请求时,此调用告诉 channel 使用 tenThreadGroup 而不是默认通道组来获取线程:
AsynchronousServerSocketChannel channel =
    AsynchronousServerSocketChannel.open(tenThreadGroup);

定义自己的通道组可更好地控制服务于操作的线程,并能提供关闭线程或者等待终止的机制。清单 3 展示了相关的例子:

清单 3. 利用通道组来控制线程关闭
// send messageByteBuffer message = ByteBuffer.wrap("Hello to all listeners".getBytes());server.send(message, new InetSocketAddress(group, port));// receive messagefinal ByteBuffer buffer = ByteBuffer.allocate(100);client.receive(buffer, null, new CompletionHandler() {    @Override    public void completed(SocketAddress address, Object attachment) {        System.out.println("Message from " + address + ": " +            new String(buffer.array()));    }    @Override    public void failed(Throwable e, Object attachment) {        System.err.println("Error receiving datagram");        e.printStackTrace();    }});

可在同一端口上创建多个客户端,它们可加入多播组来接收来自服务器的数据报。

NIO.2 的异步通道 APIs 提供方便的、平台独立的执行异步操作的标准方法。这使得应用程序开发人员能够以更清晰的方式来编写程序,而不必定义自己的 Java 线程,此外,还可通过使用底层 OS 所支持的异步功能来提高性能。如同其他 Java API 一样,API 可利用的 OS 自有异步功能的数量取决于其对该平台的支持程度。

热点排行