JAvaのBIO実装

4062 ワード

概要
このブログでは、BIOの使用や使用に問題があることを主に説明しています.
シングルスレッド処理
package one;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * BIO   
 */
public class BioService1 {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10101);
        System.out.println("     !");
        while (true){
            //       (  )
            final Socket socket = serverSocket.accept();
            System.out.println("        !");
            //    
            handler(socket);
        }
    }

    /**
     *     
     * @param socket
     */
    private static void handler(Socket socket){
        try{
            byte[] bytes = new byte[1024];
            InputStream inputStream = socket.getInputStream();
            while (true){
                //       
                int read = inputStream.read(bytes);
                if(read != -1){
                    System.out.println(new String(bytes,0,read));
                }else{
                    break;
                }
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            try{
                System.out.println("socket  ");
                socket.close();
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
    }
}

この例は、対応するソケットを取得する場合、データを読み出す場合、telnetツールを使用してプログラムを実行することによって確認できるいくつかの点ブロックポイントを説明する簡単なBIOの実装です.
上記のdemoに存在する問題は、このdemoを実行し、telnetテストにより、このサービス側は一度に1つのクライアントの要求しか受信できないことが分かった.すなわち、サービス側が1つのクライアントの要求を受信した後、サービス側がデータの読み取りにブロックされた場合、別のクライアントがそのサービス側にリンクを要求し、サーバ側はそのリンクを受信できない.サーバ側には1つのスレッドしかありませんが、このスレッドはブロックされています.サーバ側に複数のクライアントを同時に処理する要求を実現させるには,マルチスレッドによる解決が可能である.
マルチスレッドの処理
package one;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 *             
 */
public class BioService2 {
    public static void main(String[] args) throws IOException {
        ExecutorService newCashedThreadPool = Executors.newCachedThreadPool();
        ServerSocket serverSocket = new ServerSocket(10101);
        System.out.println("     !");
        while (true){
            //       (  )
            final Socket socket = serverSocket.accept();
            System.out.println("        !");
            newCashedThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    //    
                    handler(socket);
                }
            });
        }
    }

    /**
     *     
     * @param socket
     */
    private static void handler(Socket socket){
        try{
            byte[] bytes = new byte[1024];
            InputStream inputStream = socket.getInputStream();
            while (true){
                //       
                int read = inputStream.read(bytes);
                if(read != -1){
                    System.out.println(new String(bytes,0,read));
                }else{
                    break;
                }
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            try{
                System.out.println("socket  ");
                socket.close();
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
    }
}

サーバ側は、クライアント・リンクを受信するたびに、ビジネス処理のためにスレッドを作成します.すなわち、各リンクには、サービスのために個別のスレッドがあります.この方法は非常にリソースを消費し、この方法で要求されるリンクはすべて短い接続であり、この要求によって、各リンクが占有するスレッドの時間を最小限に抑え、より多くのリンク処理を行うことができる.
まとめ
単一スレッドのサーバ側では、毎回1つのクライアント要求しか処理できません.マルチスレッドのサーバ側は、受信クライアントリンクとトラフィックを分離し、トラフィック処理にマルチスレッドを使用し、複数のクライアント単一要求、すなわち、1つのクライアント1つのスレッドを処理することができ、この方法は非常にリソースを消費する.
ここで強調したいのは、サービス側がクライアントの要求を持つリンクは、tcpのリンクキャッシュ領域から取られていることです.もちろん、キャッシュ領域はどのくらいのリンク数をキャッシュすることができ、これらのパラメータも設定できます.