JAva ioとjava nio
5969 ワード
1. java io
通常、同期I/O操作を行う場合、データを読み込むと、読み取り可能なデータがあるまでコードがブロックされます.同様に、書き込み呼び出しは、データが書き込まれるまでブロックされます.従来のServer/ClientモードはTPR(Thread per Request)に基づいており、サーバはクライアント要求ごとにスレッドを作成し、このスレッドによってクライアント要求を個別に処理します.このモードがもたらす問題の1つは、スレッドの数が急増し、大量のスレッドがサーバのオーバーヘッドを増大させることです.多くの実装では、この問題を回避するためにスレッドプールモデルが採用され、スレッドプールスレッドの最大数が設定されています.これは、スレッドプールに200スレッドがあり、200人のユーザーが大きなファイルダウンロードを行っている場合、201番目のユーザーの要求がタイムリーに処理できないためです.201番目のユーザーが数KBサイズのページを要求したいだけであっても.従来のServer/Clientモードは次の図のようになります.
サービス側ソース:
クライアントソース:
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.異なるイベントに応じた対応処理
通常、同期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.異なるイベントに応じた対応処理