Java-nio-selector

提供:Dev Guides
移動先:案内検索

Java NIO-セレクター

私たちが知っているように、Java NIOはチャネルとバッファからの複数のトランザクションをサポートしているため、1つ以上のNIOチャネルを調べ、どのチャネルがデータトランザクションの準備ができているか、つまりJava NIOがセレクタを読み書きするかを判断します。

Selectorを使用すると、どのチャネルがデータの書き込みと読み取りの準備ができており、その特定のチャネルを処理できるかを知るスレッドを作成できます。

静的メソッド* open()*を呼び出すことでセレクターインスタンスを取得できます。セレクターを開いた後、SelectionKeyのインスタンスを返す非ブロッキングモードチャネルを登録する必要があります。

SelectionKeyは基本的に、チャネルで実行できる操作のコレクションです。または、選択キーを使用してチャネルの状態を知ることができます。

選択キーで表されるチャネルの主要な操作または状態は次のとおりです-

  • SelectionKey.OP_CONNECT -サーバーに接続する準備ができているチャネル。
  • SelectionKey.OP_ACCEPT -着信接続を受け入れる準備ができているチャネル。
  • SelectionKey.OP_READ -データ読み取りの準備ができているチャネル。
  • SelectionKey.OP_WRITE -データ書き込みの準備ができているチャネル。

登録後に取得される選択キーには、以下で説明するようにいくつかの重要な方法があります-

  • * attach()*-このメソッドは、キーでオブジェクトをアタッチするために使用されます。オブジェクトをチャネルにアタッチする主な目的は、同じチャネルを認識することです。
  • * attachment()*-このメソッドは、チャネルからアタッチされたオブジェクトを保持するために使用されます。
  • * channel()*-このメソッドは、特定のキーが作成されるチャネルを取得するために使用されます。
  • * selector()*-このメソッドは、特定のキーが作成されるセレクターを取得するために使用されます。
  • * isValid()*-このメソッドは、キーが有効かどうかの天気を返します。
  • * isReadable()*-このメソッドは、天気キーのチャネルが読み取り可能かどうかを示します。
  • * isWritable()*-このメソッドは、天気キーのチャネルが書き込み可能かどうかを示します。
  • * isAcceptable()*-このメソッドは、天気キーのチャネルが着信接続を受け入れる準備ができているかどうかを示します。
  • * isConnectable()*-このメソッドは、このキーのチャネルがソケット接続操作を終了したか、終了に失敗したかをテストします。
  • * isAcceptable()*-このメソッドは、このキーのチャネルが新しいソケット接続を受け入れる準備ができているかどうかをテストします。
  • * interestOps()*-このメソッドは、このキーの対象セットを取得します。
  • * readyOps()*-このメソッドは、チャネルが準備ができている操作のセットである準備セットを取得します。

セレクタの静的メソッド* select()*を呼び出すことで、セレクタからチャネルを選択できます。セレクタのSelectメソッドは次のようにオーバーロードされます-

  • * select()*-このメソッドは、少なくとも1つのチャネルが登録されたイベントの準備ができるまで、現在のスレッドをブロックします。
  • * select(long timeout)*-このメソッドはselect()と同じですが、最大タイムアウトミリ秒(パラメーター)スレッドをブロックします。
  • * selectNow()*-このメソッドはまったくブロックせず、準備ができているチャンネルをすぐに返します。

また、selectメソッドを呼び出すブロックされたスレッドを残すために、select()内で待機しているスレッドがすぐに戻るセレクターインスタンスから* wakeup()*メソッドを呼び出すことができます。

最後に、セレクターを閉じると同時にこのセレクターに登録されたすべてのSelectionKeyインスタンスを無効にする* close()*メソッドを呼び出して、セレクターを閉じることができます。

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class SelectorDemo {
   public static void main(String[] args) throws IOException {
      String demo_text = "This is a demo String";
      Selector selector = Selector.open();
      ServerSocketChannel serverSocket = ServerSocketChannel.open();
      serverSocket.bind(new InetSocketAddress("localhost", 5454));
      serverSocket.configureBlocking(false);
      serverSocket.register(selector, SelectionKey.OP_ACCEPT);
      ByteBuffer buffer = ByteBuffer.allocate(256);
      while (true) {
         selector.select();
         Set<SelectionKey> selectedKeys = selector.selectedKeys();
         Iterator<SelectionKey> iter = selectedKeys.iterator();
         while (iter.hasNext()) {
            SelectionKey key = iter.next();
            int interestOps = key.interestOps();
            System.out.println(interestOps);
            if (key.isAcceptable()) {
               SocketChannel client = serverSocket.accept();
               client.configureBlocking(false);
               client.register(selector, SelectionKey.OP_READ);
            }
            if (key.isReadable()) {
               SocketChannel client = (SocketChannel) key.channel();
               client.read(buffer);
               if (new String(buffer.array()).trim().equals(demo_text)) {
                  client.close();
                  System.out.println("Not accepting client messages anymore");
               }
               buffer.flip();
               client.write(buffer);
               buffer.clear();
            }
            iter.remove();
         }
      }
   }
}