1. 概要

この記事では、Java7の新しいI/ O(NIO2)の主要な追加APIの1つである非同期チャネルAPIの基盤について説明します。

これは、この特定のトピックをカバーする一連の記事の最初のものです。

非同期チャネルAPIは、Java1.4に付属していた以前の新しいI/ O(NIO)APIを拡張したものです。 NIOセレクターについて読むには、このリンクをたどってください。

NIO APIのもう1つの拡張機能は、新しいファイルシステムAPIです。 このサイトでも、ファイル操作およびパス操作の詳細を読むことができます。

プロジェクトでNIO2非同期チャネルを使用するには、必要なクラスがバンドルされているため、java.nio.channelsパッケージをインポートする必要があります。

import java.nio.channels.*;

2. 非同期チャネルAPIのしくみ

非同期チャネルAPIは、既存の java.nio.channels パッケージに導入されました。簡単に言えば、クラス名の前にAsynchronousという単語を付けることです。

コアクラスには、 AsynchronousSocketChannel AsynchronousServerSocketChannel 、およびAsynchronousFileChannelが含まれます。

お気づきかもしれませんが、これらのクラスは、標準のNIOチャネルAPIとスタイルが似ています。

また、NIOチャネルクラスで使用できるほとんどのAPI操作は、新しい非同期バージョンでも使用できます。 主な違いは、新しいチャネルにより、一部の操作を非同期で実行できるようになることです

操作が開始されると、非同期チャネルAPIは、保留中の操作を監視および制御するための2つの選択肢を提供します。 この操作では、 java.util.concurrent.Future オブジェクトを返すか、java.nio.channels.CompletionHandlerを渡すことができます。

3. Futureアプローチ

Futureオブジェクトは、非同期計算の結果を表します。クライアント接続をリッスンするサーバーを作成する場合、AsynchronousServerSocketChannelで静的openAPIを呼び出します。 ]そしてオプションで返されたソケットチャネルをアドレスにバインドします:

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

システムがアドレスを自動割り当てできるように、nullを渡しました。 次に、返されたサーバーSocketChannelacceptメソッドを呼び出します。

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

古いIOでServerSocketChannelacceptメソッドを呼び出すと、クライアントから着信接続が受信されるまでブロックされます。 ただし、AsynchronousServerSocketChannelacceptメソッドは、Futureオブジェクトをすぐに返します。

Future オブジェクトの汎用タイプは、操作の戻りタイプです。 上記の場合、それは AsynchronousSocketChannel ですが、操作の最終的な戻りタイプに応じて、IntegerまたはStringである可能性もあります。

Future オブジェクトを使用して、操作の状態を照会できます。

future.isDone();

基になる操作がすでに完了している場合、このAPIはtrueを返します。 この場合、完了は通常の終了、例外、またはキャンセルを意味する場合があることに注意してください。

操作がキャンセルされたかどうかを明示的に確認することもできます。

future.isCancelled();

操作が正常に完了する前にキャンセルされた場合にのみtrueを返し、それ以外の場合はfalseを返します。 キャンセルは、キャンセルメソッドによって実行されます。

future.cancel(true);

この呼び出しは、Futureオブジェクトによって表される操作をキャンセルします。 このパラメーターは、操作が開始された場合でも、操作が中断される可能性があることを示しています。 操作が完了すると、キャンセルすることはできません

計算結果を取得するには、getメソッドを使用します。

AsynchronousSocketChannel client= future.get();

操作が完了する前にこのAPIを呼び出すと、操作が完了するまでブロックされ、操作の結果が返されます。

4. CompleteHandlerアプローチ

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
      }
  });

完了したコールバックAPIは、I/O操作が正常に完了したときに呼び出されます。 操作が失敗した場合、failedコールバックが呼び出されます。

これらのコールバックメソッドは他のパラメーターを受け入れます。これにより、操作とともにタグ付けするのに適していると思われるデータを渡すことができます。 この最初のパラメーターは、コールバックメソッドの2番目のパラメーターとして使用できます。

最後に、明確なシナリオは–異なる非同期操作に同じCompletionHandlerを使用することです。 この場合、結果を処理するときにコンテキストを提供するために各操作にタグを付けると、次のセクションでこれが実際に動作することを確認できます。

5. 結論

この記事では、JavaNIO2の非同期チャネルAPIの紹介的な側面について説明しました。

この記事のすべてのコードスニペットと完全なソースコードを入手するには、GitHubプロジェクトにアクセスしてください。