Java NIOとリアクターモード


一、Java NIOプロフィールJava NIO非ブロックアプリケーションは通常I/O読み書きなどに適用される.システムが動作するパフォーマンスのボトルネックは、ポートやファイルの操作を含むI/O読み書きにあることがよく知られています.従来、I/Oチャネルを開くと、read()はポートがバイトコンテンツを読み出すのを一度待っていたため、リソースが非常に消費されました.
Java NIO非ブロック技術は実際にReactorモードを採用している.彼はI/Oポートを監視してくれて、もし内容が入ってきたら、自動的に私たちに知らせてくれます.そうすれば、私たちは複数のスレッドの死などを開く必要はありません.外部から見ると、スムーズなI/O読み書きを実現し、ブロックされません.
二、NIOの基本原理NIOには主なクラスSelectorがあります.これは観察者のようなものです.私たちが探知する必要があるsocketchannelをselectorに伝えさえすれば、私たちは他のことをします.何かあったら、彼は私たちに知らせて、selectionkeyのグループに戻って、私たちはこれらのkeyを読んで、私たちが登録したばかりのsocketchannelを手に入れます.そして、私たちはこのchannelからデータを読み出します.
selectorの内部原理は実際に登録されたchannelへのポーリングアクセスを行い、絶えずポーリングを行い、このchannelにポーリングして登録されたことが発生すると、データが来たら、彼は立ち上がって報告し、鍵を渡して、この鍵を通じてこのchannelの内容を読み取りましょう.
使用上:
 package reactor.section3;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
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 NBTest1 {



    private static void printKeyInfo(SelectionKey sk) {
        String s = new String();
        s += "Att: " + (sk.attachment() == null ? "no" : "yes");
        s += ", Read: " + sk.isReadable();
        s += ", Acpt: " + sk.isAcceptable();
        s += ", Cnct: " + sk.isConnectable();
        s += ", Wrt: " + sk.isWritable();
        s += ", Valid: " + sk.isValid();
        s += ", Ops: " + sk.interestOps();
        debug(s);
    }
    private static void debug(String s) {
        System.out.println(s);
    }
    public static void main(String args[]) {
        NBTest1 nbTest = new NBTest1();
        try {
            nbTest.startServer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private void startServer()  throws Exception{
        int channels = 0;
        int nKeys = 0;
        int currentSelector = 0;

        //  Selector
        Selector selector = Selector.open();

        //  Channel     9000  
        ServerSocketChannel ssc = ServerSocketChannel.open();
        InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(),9000); 
        ssc.socket().bind(address);

        //   non-blocking   。
        ssc.configureBlocking(false);

        // Selector  Channel         
        SelectionKey s = ssc.register(selector, SelectionKey.OP_ACCEPT);
        printKeyInfo(s);
        while(true) //     
        {

            debug("NBTest: Starting select");
            //Selector  select                 。
            nKeys = selector.select();
            //             ,         0
            if(nKeys > 0){
                debug("NBTest: Number of keys after select operation: " +nKeys);

                Set selectedKeys = selector.selectedKeys();
                Iterator i = selectedKeys.iterator();
                while(i.hasNext()){

                    s = (SelectionKey) i.next();
                    printKeyInfo(s);
                    debug("NBTest: Nr Keys in selector: " +selector.keys().size());
                    //  key      ,         (ready keys)     
                    i.remove();
                    if(s.isAcceptable()){
                        //  channel()          channel。
                        Socket socket = ((ServerSocketChannel)s.channel()).accept().socket();
                        SocketChannel sc = socket.getChannel();
                        sc.configureBlocking(false);
                        sc.register(selector, SelectionKey.OP_READ |SelectionKey.OP_WRITE);
                        System.out.println(++channels);
                    }else{
                        debug("NBTest: Channel not acceptable");
                    }
                }



            }else{
                debug("NBTest: Select finished without any keys.");
            }

        }

    }
}

これは、ポート9000に待機しているnoblock serverの例です.クライアントプログラムを作成すると、インタラクティブに操作したり、telnetホスト名90000を使用してリンクしたりすることができます.