NIOとIO
4481 ワード
次の表では、Java NIOとIOの主な違いをまとめ、表の各部分の違いをより詳細に説明します.
ストリーム向けおよびバッファ向け
Java NIOとIOの最初の最大の違いは,IOがストリーム向けであり,NIOがバッファ向けであることである.Java IOがストリームに面していることは、ストリームから1つ以上のバイトを読み出すたびに、すべてのバイトが読み込まれるまで、どこにもキャッシュされていないことを意味します.また、ストリーム内のデータを前後に移動することはできません.ストリームから読み込まれたデータを前後に移動する必要がある場合は、まずバッファにキャッシュする必要があります.Java NIOのバッファガイド方法は少し違います.データは後で処理されるバッファに読み込まれ、必要に応じてバッファ内を前後に移動できます.これにより、処理中の柔軟性が向上します.ただし、バッファに処理するデータがすべて含まれているかどうかを確認する必要があります.また、より多くのデータがバッファに読み込まれた場合、バッファ内の未処理のデータを上書きしないようにする必要がある.
ブロックと非ブロックIO
Java IOの様々なストリームはブロックされています.これは、1つのスレッドがread()またはwrite()を呼び出すと、一部のデータが読み出されるか、データが完全に書き込まれるまでスレッドがブロックされることを意味する.このスレッドはその間に何もできません.Java NIOの非ブロックモードでは、スレッドがチャネルからデータの読み取りを要求するように送信されますが、現在使用可能なデータしか得られません.現在使用可能なデータがない場合、何も取得されません.スレッドのブロックを維持するのではなく、データが読み取れるまでスレッドは他のことを続けることができます.ブロックされていない書き込みもそうです.1つのスレッドは、チャネルにデータの書き込みを要求しますが、完全な書き込みを待つ必要はありません.このスレッドは同時に他のことをすることができます.スレッドは通常、IOをブロックしないアイドル時間を他のチャネルでIO操作を実行するために使用するので、1つの個別のスレッドは、複数の入出力チャネル(channel)を管理することができるようになった.
セレクタ(Selectors)
Java NIOのセレクタでは、複数の入力チャネルを監視するために個別のスレッドを使用できます.複数のチャネルを登録してセレクタを使用し、個別のスレッドを使用してチャネルを選択できます.これらのチャネルにはすでに処理可能な入力があるか、書き込みの準備ができているチャネルを選択できます.この選択メカニズムにより、1つの個別のスレッドが複数のチャネルを管理しやすくなります.
NIOとIOがアプリケーションの設計にどのように影響するか
IOまたはNIOツールボックスを選択しても、アプリケーションの設計に影響を与える可能性があります.
1.NIOまたはIOクラスに対するAPI呼び出し.2.データ処理.3.データを処理するスレッドの数.
API呼び出し
もちろん、NIOのAPI呼び出しを使用する場合はIOを使用する場合とは異なるように見えますが、これは意外ではありません.1つのInputStreamからバイト単位で読み取るのではなく、データがバッファに読み込まれてから処理される必要があるからです.
データしょり
純粋なNIO設計を用いてIO設計に比べてデータ処理にも影響を与えた.
IO設計では,InputStreamまたはReaderからバイト毎にデータを読み出す.行ベースのテキスト・データ・ストリームを処理しているとします.たとえば、次のようにします.
このテキスト行のストリームは、次のように処理できます.
処理状態は、プログラムがどのくらい実行するかによって決定されることに注意してください.言い換えればreader.readLine()メソッドが戻ると、肯定テキスト行が読み終わったことがわかります.readline()は行全体が読み終わるまでブロックされます.これが原因です.この行には名前が含まれていることも知っています.同様に、2番目のreadline()呼び出しが返されると、この行には年齢などが含まれていることがわかります.ご覧のように、このプロセッサは新しいデータの読み込み時にのみ実行され、各ステップのデータが何であるかを知っています.実行中のスレッドが読み込まれたデータの一部を処理した場合、そのスレッドはデータをロールバックしません(ほとんどはそうです).次の図もこの原則を示しています.
(Java IO:ブロックされたストリームからデータを読み出す)NIOの実装は異なります.以下は簡単な例です.
2行目は、チャネルからByteBufferにバイトを読み込みます.このメソッドが戻ってくると、必要なすべてのデータがバッファ内にあるかどうか分かりません.バッファにはいくつかのバイトが含まれており、処理が困難であることを知っています.最初のread(buffer)呼び出し後、バッファに読み込まれたデータが半行しかないとします.たとえば、「Name:An」ですが、データを処理できますか.明らかにできません.行全体のデータがキャッシュに読み込まれるまで待つ必要があります.その前に、データの処理には意味がありません.
だから、バッファに十分なデータが含まれているかどうかをどうやって知っていますか?わかった、君は知らない.検出されたメソッドは、バッファ内のデータのみを表示できます.その結果、すべてのデータがバッファ内にあることを知る前に、バッファのデータを何回かチェックする必要があります.これは効率が悪いだけでなく、プログラム設計案を乱雑にすることができる.例:
bufferFull()メソッドは、バッファが満たされているかどうかに応じて、バッファに読み込まれたデータの数を追跡し、真または偽を返す必要があります.すなわち、バッファが処理される準備ができている場合は、バッファがいっぱいであることを示す.
bufferFull()メソッドはバッファをスキャンしますが、bufferFull()メソッドが呼び出される前に同じ状態に保たなければなりません.そうでない場合、次のバッファに読み込まれたデータが正しい位置に読めない可能性があります.これは不可能ですが、注意が必要なもう一つの問題です.
バッファが満たされている場合は、処理できます.不満があり、実際のケースで意味がある場合は、データの一部を処理できるかもしれません.しかし、多くの場合そうではありません.次の図は、バッファ・データ・ループの準備を示しています.
3)データ処理のためのスレッド数
NIOは、1つ(または複数)の単一スレッドのみを使用して複数のチャネル(ネットワーク接続またはファイル)を管理できますが、1つのブロックフローからデータを読み出すよりも解析データが複雑になる可能性があります.
同時に開いている何千もの接続を管理する必要がある場合は、チャットサーバなどの少量のデータを送信するたびに、NIOを実現するサーバがメリットになる可能性があります.同様に、P 2 Pネットワークなどの他のコンピュータへの多くのオープン接続を維持する必要がある場合は、個別のスレッドを使用してすべてのアウトバウンド接続を管理することがメリットかもしれません.1つのスレッドの複数の接続の設計案は、次のようになります.
Java NIO:シングルスレッド管理複数接続
少量の接続で非常に高い帯域幅を使用している場合は、一度に大量のデータを送信すると、典型的なIOサーバ実装が非常に適している可能性があります.次の図は、典型的なIOサーバ設計を示しています.
Java IO:典型的なIOサーバ設計-接続がスレッドで処理される
IO NIO
IO IO
ストリーム向けおよびバッファ向け
Java NIOとIOの最初の最大の違いは,IOがストリーム向けであり,NIOがバッファ向けであることである.Java IOがストリームに面していることは、ストリームから1つ以上のバイトを読み出すたびに、すべてのバイトが読み込まれるまで、どこにもキャッシュされていないことを意味します.また、ストリーム内のデータを前後に移動することはできません.ストリームから読み込まれたデータを前後に移動する必要がある場合は、まずバッファにキャッシュする必要があります.Java NIOのバッファガイド方法は少し違います.データは後で処理されるバッファに読み込まれ、必要に応じてバッファ内を前後に移動できます.これにより、処理中の柔軟性が向上します.ただし、バッファに処理するデータがすべて含まれているかどうかを確認する必要があります.また、より多くのデータがバッファに読み込まれた場合、バッファ内の未処理のデータを上書きしないようにする必要がある.
ブロックと非ブロックIO
Java IOの様々なストリームはブロックされています.これは、1つのスレッドがread()またはwrite()を呼び出すと、一部のデータが読み出されるか、データが完全に書き込まれるまでスレッドがブロックされることを意味する.このスレッドはその間に何もできません.Java NIOの非ブロックモードでは、スレッドがチャネルからデータの読み取りを要求するように送信されますが、現在使用可能なデータしか得られません.現在使用可能なデータがない場合、何も取得されません.スレッドのブロックを維持するのではなく、データが読み取れるまでスレッドは他のことを続けることができます.ブロックされていない書き込みもそうです.1つのスレッドは、チャネルにデータの書き込みを要求しますが、完全な書き込みを待つ必要はありません.このスレッドは同時に他のことをすることができます.スレッドは通常、IOをブロックしないアイドル時間を他のチャネルでIO操作を実行するために使用するので、1つの個別のスレッドは、複数の入出力チャネル(channel)を管理することができるようになった.
セレクタ(Selectors)
Java NIOのセレクタでは、複数の入力チャネルを監視するために個別のスレッドを使用できます.複数のチャネルを登録してセレクタを使用し、個別のスレッドを使用してチャネルを選択できます.これらのチャネルにはすでに処理可能な入力があるか、書き込みの準備ができているチャネルを選択できます.この選択メカニズムにより、1つの個別のスレッドが複数のチャネルを管理しやすくなります.
NIOとIOがアプリケーションの設計にどのように影響するか
IOまたはNIOツールボックスを選択しても、アプリケーションの設計に影響を与える可能性があります.
1.NIOまたはIOクラスに対するAPI呼び出し.2.データ処理.3.データを処理するスレッドの数.
API呼び出し
もちろん、NIOのAPI呼び出しを使用する場合はIOを使用する場合とは異なるように見えますが、これは意外ではありません.1つのInputStreamからバイト単位で読み取るのではなく、データがバッファに読み込まれてから処理される必要があるからです.
データしょり
純粋なNIO設計を用いてIO設計に比べてデータ処理にも影響を与えた.
IO設計では,InputStreamまたはReaderからバイト毎にデータを読み出す.行ベースのテキスト・データ・ストリームを処理しているとします.たとえば、次のようにします.
Name: Anna
Age: 25
Email: [email protected]
Phone: 1234567890
このテキスト行のストリームは、次のように処理できます.
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String nameLine = reader.readLine();
String ageLine = reader.readLine();
String emailLine = reader.readLine();
String phoneLine = reader.readLine();
処理状態は、プログラムがどのくらい実行するかによって決定されることに注意してください.言い換えればreader.readLine()メソッドが戻ると、肯定テキスト行が読み終わったことがわかります.readline()は行全体が読み終わるまでブロックされます.これが原因です.この行には名前が含まれていることも知っています.同様に、2番目のreadline()呼び出しが返されると、この行には年齢などが含まれていることがわかります.ご覧のように、このプロセッサは新しいデータの読み込み時にのみ実行され、各ステップのデータが何であるかを知っています.実行中のスレッドが読み込まれたデータの一部を処理した場合、そのスレッドはデータをロールバックしません(ほとんどはそうです).次の図もこの原則を示しています.
(Java IO:ブロックされたストリームからデータを読み出す)NIOの実装は異なります.以下は簡単な例です.
ByteBuffer buffer = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buffer);
2行目は、チャネルからByteBufferにバイトを読み込みます.このメソッドが戻ってくると、必要なすべてのデータがバッファ内にあるかどうか分かりません.バッファにはいくつかのバイトが含まれており、処理が困難であることを知っています.最初のread(buffer)呼び出し後、バッファに読み込まれたデータが半行しかないとします.たとえば、「Name:An」ですが、データを処理できますか.明らかにできません.行全体のデータがキャッシュに読み込まれるまで待つ必要があります.その前に、データの処理には意味がありません.
だから、バッファに十分なデータが含まれているかどうかをどうやって知っていますか?わかった、君は知らない.検出されたメソッドは、バッファ内のデータのみを表示できます.その結果、すべてのデータがバッファ内にあることを知る前に、バッファのデータを何回かチェックする必要があります.これは効率が悪いだけでなく、プログラム設計案を乱雑にすることができる.例:
ByteBuffer buffer = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buffer);
while(! bufferFull(bytesRead) ) {
bytesRead = inChannel.read(buffer);
}
bufferFull()メソッドは、バッファが満たされているかどうかに応じて、バッファに読み込まれたデータの数を追跡し、真または偽を返す必要があります.すなわち、バッファが処理される準備ができている場合は、バッファがいっぱいであることを示す.
bufferFull()メソッドはバッファをスキャンしますが、bufferFull()メソッドが呼び出される前に同じ状態に保たなければなりません.そうでない場合、次のバッファに読み込まれたデータが正しい位置に読めない可能性があります.これは不可能ですが、注意が必要なもう一つの問題です.
バッファが満たされている場合は、処理できます.不満があり、実際のケースで意味がある場合は、データの一部を処理できるかもしれません.しかし、多くの場合そうではありません.次の図は、バッファ・データ・ループの準備を示しています.
3)データ処理のためのスレッド数
NIOは、1つ(または複数)の単一スレッドのみを使用して複数のチャネル(ネットワーク接続またはファイル)を管理できますが、1つのブロックフローからデータを読み出すよりも解析データが複雑になる可能性があります.
同時に開いている何千もの接続を管理する必要がある場合は、チャットサーバなどの少量のデータを送信するたびに、NIOを実現するサーバがメリットになる可能性があります.同様に、P 2 Pネットワークなどの他のコンピュータへの多くのオープン接続を維持する必要がある場合は、個別のスレッドを使用してすべてのアウトバウンド接続を管理することがメリットかもしれません.1つのスレッドの複数の接続の設計案は、次のようになります.
Java NIO:シングルスレッド管理複数接続
少量の接続で非常に高い帯域幅を使用している場合は、一度に大量のデータを送信すると、典型的なIOサーバ実装が非常に適している可能性があります.次の図は、典型的なIOサーバ設計を示しています.
Java IO:典型的なIOサーバ設計-接続がスレッドで処理される