JAva ioとjava nio

5969 ワード

1. java io
通常、同期I/O操作を行う場合、データを読み込むと、読み取り可能なデータがあるまでコードがブロックされます.同様に、書き込み呼び出しは、データが書き込まれるまでブロックされます.従来のServer/ClientモードはTPR(Thread per Request)に基づいており、サーバはクライアント要求ごとにスレッドを作成し、このスレッドによってクライアント要求を個別に処理します.このモードがもたらす問題の1つは、スレッドの数が急増し、大量のスレッドがサーバのオーバーヘッドを増大させることです.多くの実装では、この問題を回避するためにスレッドプールモデルが採用され、スレッドプールスレッドの最大数が設定されています.これは、スレッドプールに200スレッドがあり、200人のユーザーが大きなファイルダウンロードを行っている場合、201番目のユーザーの要求がタイムリーに処理できないためです.201番目のユーザーが数KBサイズのページを要求したいだけであっても.従来のServer/Clientモードは次の図のようになります.
 サービス側ソース:
package com.defonds.socket.begin;  
  
import java.io.BufferedReader;  
import java.io.DataInputStream;  
import java.io.DataOutputStream;  
import java.io.InputStreamReader;  
import java.net.ServerSocket;  
import java.net.Socket;  
  
public class Server {  
    public static final int PORT = 12345;//           
      
    public static void main(String[] args) {    
        System.out.println("     ...
"); Server server = new Server(); server.init(); } public void init() { try { ServerSocket serverSocket = new ServerSocket(PORT); while (true) { // , Socket client = serverSocket.accept(); // new HandlerThread(client); } } catch (Exception e) { System.out.println(" : " + e.getMessage()); } } private class HandlerThread implements Runnable { private Socket socket; public HandlerThread(Socket client) { socket = client; new Thread(this).start(); } public void run() { try { // DataInputStream input = new DataInputStream(socket.getInputStream()); String clientInputStr = input.readUTF();// , EOFException // System.out.println(" :" + clientInputStr); // DataOutputStream out = new DataOutputStream(socket.getOutputStream()); System.out.print(" :\t"); // String s = new BufferedReader(new InputStreamReader(System.in)).readLine(); out.writeUTF(s); out.close(); input.close(); } catch (Exception e) { System.out.println(" run : " + e.getMessage()); } finally { if (socket != null) { try { socket.close(); } catch (Exception e) { socket = null; System.out.println(" finally :" + e.getMessage()); } } } } } }

クライアントソース:
package com.defonds.socket.begin;  
  
import java.io.BufferedReader;  
import java.io.DataInputStream;  
import java.io.DataOutputStream;  
import java.io.IOException;  
import java.io.InputStreamReader;  
import java.net.Socket;  
  
public class Client {  
    public static final String IP_ADDR = "localhost";//        
    public static final int PORT = 12345;//          
      
    public static void main(String[] args) {    
        System.out.println("     ...");    
        System.out.println("            \"OK\"    ,       
"); while (true) { Socket socket = null; try { // socket = new Socket(IP_ADDR, PORT); // DataInputStream input = new DataInputStream(socket.getInputStream()); // DataOutputStream out = new DataOutputStream(socket.getOutputStream()); System.out.print(" : \t"); String str = new BufferedReader(new InputStreamReader(System.in)).readLine(); out.writeUTF(str); String ret = input.readUTF(); System.out.println(" : " + ret); // "OK" if ("OK".equals(ret)) { System.out.println(" "); Thread.sleep(500); break; } out.close(); input.close(); } catch (Exception e) { System.out.println(" :" + e.getMessage()); } finally { if (socket != null) { try { socket.close(); } catch (IOException e) { socket = null; System.out.println(" finally :" + e.getMessage()); } } } } } }

2 . java NIO
NIOにおける非ブロックI/OはReactorモードに基づく動作方式を採用しており、I/O呼び出しはブロックされず、逆に興味のある特定のI/Oイベント、例えば可読データ到着、新しいソケット接続などを登録し、特定のイベントが発生した場合、システムから通知される.NIOで非ブロックI/Oを実現するコアオブジェクトはSelectorであり、Selectorは各種I/Oイベントを登録する場所であり、それらのイベントが発生した場合、このオブジェクトが私たちに発生したイベントを教えてくれます.下図のように:
図から分かるように、リードまたはライトなどの登録されたイベントが発生した場合、対応するSelectorからSelectionKeyを取得することができ、同時にSelectionKeyから発生したイベントとそのイベントが発生した特定のSelectableChannelを見つけることができ、クライアントから送信されたデータを取得することができる.
NIOの非ブロックI/Oを使用してサーバハンドラを記述するには、大きく次の3つのステップに分けることができます.
1.Selectorオブジェクトに興味のあるイベントを登録する  2.Selectorから興味のあるイベントを取得  3.異なるイベントに応じた対応処理