NIO の基本、マルチスレッド、スレッド プール、セレクターの違い

NIO-ベーシック

ここに画像の説明を挿入
ここに画像の説明を挿入

一方向チャネル:

入出力ストリームはデータ伝送用のチャネルですが、単なる一方向のチャネルです。たとえば、入力ストリームの場合、ファイルとネットワークからのデータのみを読み取ることができます。出力ストリームはファイルとネットワークにのみデータを出力でき、これは一方向です。

双方向チャンネル

チャネルは双方向データチャネルです。データの入力だけでなくデータの出力にも使用できます。
入力データはメモリに一時的にデータを格納する必要があり、バッファとはチャネルから読み取ったデータを一時的に格納するメモリバッファです。逆に、そこにデータを書き込みたい場合は、まずデータをバッファに一時的に保存する必要があります。

  • FileVhannel: ファイルのデータ送信チャネルとして。

  • DatagramChannel: udp ネットワーク プログラミングを行う場合、データ伝送チャネルです。

  • socketChannelとサーバーソケットチャネルはTCPリアルタイムデータの送信チャネルとみなされます

  • バッファ: データをバイト単位でバッファリングします。抽象クラスです。バッファは抽象クラスの実装クラスです。サポートされているさまざまなデータ型のバッファであるマップ バッファなどがあります。たとえば、ショート バッファ、 Float double char は、実際にはさまざまな基本データ型に対応します。ただし、後者はあまり使用されず、最も一般的に使用されるのはバイトです

マルチスレッド化

ここに画像の説明を挿入
クライアントは読み取りおよび書き込み操作を実行し、サーバー側で新しいスレッドを開始してソケットにサービスを提供できます。読み取りおよび書き込み操作はすべてこのスレッド内で完了します。
複数のクライアントと複数のソケット接続がある場合、サーバーは複数のスレッドを開く必要があります。各スレッドはリンク専用です。これは、サーバー側設計のマルチスレッド バージョンです。
このデザインの欠点や欠点は何ですか?接続数が多いと麻痺してしまいます
が、接続数が比較的少ない場合は、このマルチスレッド バージョンの設計で問題ありません。しかし、多数の接続を処理するサービスを設計するには、それは機能しません。なぜなら。クライアントがスレッドを使用して処理する場合、スレッド自体が一定量のメモリを占有します。たとえば、デフォルトでは、Windows のデフォルト スレッドは 1 メガバイトのメモリを占有します。1000に到達しました。クライアントは 1000 の接続を確立しており、スレッドによって占有されるメモリの数は 1000、つまり 1 メガバイトを掛けると 1 G になります。当然ですが、接続数が増えると、まずメモリが持ちこたえられなくなり、メモリ不足になる可能性があります。メモリ不足です。ここに比喩があります。サーバーがレストランであり、これらのソケットがレストランに食事をしに来るゲストであるようなものです。マルチスレッド バージョンのサーバー設計は次のようになります。1 人のゲストが 1 人のウェイターに対応します。
同時に、スレッド数が増加しても、CPU はそれに追いつくことができます。スレッド内のコードが実際に実行されるためです。実行するCPUに依存します。たとえば、CPU が 16 個しかない場合、実際に同時に実行できるコード、または同時に実行できるスレッドの数は 16 個だけです。その後、他のスレッドは待機する必要があります。これらのスレッドが待機しているとき。これらのスレッドの現在の実行ステータスが保存されます。たとえば、スレッドが実行したコードの行や、スレッド内の一時変数は何ですか? 彼はそれを記録して保存する必要があります。余分な糸は横に置く必要があります。その後、これらのスレッドが将来実行される番となり、彼はこれらの状態を再度復元する必要があります。これはスレッドのコンテキストスイッチと呼ばれるもので、比較的コストがかかります。
レストランの例を見てみましょう。私のレストランには合計 16 のワークステーションがある場合があります。同時にウェイターは 16 人までしか雇うことができませんが、残りのウェイターには席がないため仕事ができません。レストランの外で待つことしかできません。順番が来たら店内に入ることができます。明らかにコストがかかりすぎます。あなたたちの中の 1 人が席を空けて、その席に座ります。その場合、サービス全体の処理時間が遅くなります。これがマルチスレッド バージョンの 2 番目の欠点です。要約すると、このマルチスレッド バージョンのサーバー側設計は、接続数が少ないシナリオのみを対象としています。接続数が多いとうまく動作しない

スレッドプール

ここに画像の説明を挿入

スレッド プールは以前の問題を解決できるでしょうか?
上の図は、サーバーがスレッド プール設計を採用していることを示しています。スレッド プール内のスレッドの数は制限されています。たとえば、スレッドは 2 つだけです。将来的には、多くのクライアントが存在する可能性があります。たとえば、クライアントが 4 つあります。次に、「スレッドは複数のクライアントの読み取りおよび書き込み操作を処理できますか?」もちろん可能ですが、一定の制限があります。つまり、ソケットはブロッキング モードです。
ブロッキングモードとは何ですか? 簡単に言うと、ブロッキング モードでは、このスレッドは 1 つのソケット接続でこの操作 (読み取り操作と書き込み操作) のみを同時に処理できます。たとえば、この図では実線と点線を描いています。つまり、このスレッドは SOCKET1 を同時に処理しています。ソケット 3 を処理できません。手を解放するには、socket1 が切断されるまで待つ必要があります。これは、socket3 での接続を処理するための
メタファーであり、レストランの例です。ソケットは私たちのサーバーです。ソケット 1 についてはどうでしょうか。顧客が食事するまでには多くの手順があるかもしれません。顧客はメニューを閲覧し、注文し、食事をし、最後に請求書を支払う必要があります。ただし、顧客がすべての操作を実行するのと同時に、ウェイターも顧客に同行する必要があります。 。たとえば、彼がメニューをめくっただけで、ここで食べ物を注文しなかったとしても、それはすべてこのスレッドにあります。会計を終えた最後の客が接続を切断して初めて、ウェイターは自由になり、次のコースに進むことができました。これをブロッキングモードと呼びます。同時に、スレッドは
ソケットなどの短い接続しか処理できません。スレッドを送信して接続した後は、ビジネス プロセスを終了し、すぐに接続を切断します。切断の目的は何ですか? このスレッドを解放して他のリンクを処理できるようにするためです。私たちの初期に開設したサーバーと同様に、この方法を採用しました。オンサイトバーの設計、ブロッキング io の方が HTTP リクエストに適しています。HTTP リクエストはリクエストを送信してレスポンスを返すために接続されているため、切断することができ、スレッドが解放されて次のリクエストを処理できるようになります。これはスレッド プール ボードの欠点です。
要約すると、これは短い接続シナリオにのみ適しており、このスレッド プール バージョンの場合、ソケットはブロッキング モードで動作するため、スレッド使用率は高くありません。

セレクタ

ここに画像の説明を挿入
比喩的に言えば、スレッドはレストランのウェイターのようなものですが、この写真を通して、ウェイターは 1 人だけで十分であることに気づきました。このチャネルはそれらのゲストと同様であり、チャネルは以前のソケットと同等です。それは実際にサーバーとクライアント間の接続を表しているのでしょうか? データの読み取りおよび書き込み用のチャネルであるこのチャネルを通じて、サーバーとクライアントの間でデータの読み取りおよび書き込みが可能です。
セレクターは、すべてのゲストのニーズを監視できるツールのようなものです。として理解されます。カメラだろうが何だろうが、とにかく客の一挙手一投足が彼の監視下にある。これらのゲストからリクエストがあると、セレクターはそれを初めて認識し、サービスを提供するためにウェイターを派遣することができます。たとえば、私たちが最初に始めたとき、これらの顧客とセレクターはすべてサービスに接続されており、最初は全員がメニューに目を通していました。何も操作をしなかったのに、来客がありました。このゲストさん。彼は決断を下し、食べ物を注文し、カンパオチキンを注文しました。そしてそれが需要を教えてくれます。サーバーに送信するデータがあります。サーバーはそれをセレクターに送信し、セレクターはこのスレッドに渡されます。その後、このスレッドがゲストのリクエストを処理します。じゃあ次にまたゲストがいたら
セレクターは、複数の生産能力を管理し、複数のレベルを管理し、これらのチャネルで発生するすべてのイベントを取得できます。ただし、このイベント タイプは、接続可能、読み取り可能、書き込み可能なイベントに分けられます。これらのイベントが発生すると、この select はスレッドと連携して、このスレッドにこれらの読み取りおよび書き込み操作を特別に処理させることができます。そしてもう 1 つの点があります。彼と前述したスレッド プール バージョンとの最大の違いは、ノンブロッキング モードで動作するチャネルです。ノンブロッキングは、ソケット接続が切断される前にスレッドが存在していた以前とは異なります。ノンブロッキングを簡単に理解すると、チャネル上で唯一のスレッドがハングしないようにするということです。最初のチャネルに時間がない場合は、このスレッドが 2 番目のチャネルを処理できます。2 番目のチャネルに時間がない場合は、他のスレッドが 3 番目のチャネルを処理できます。このスレッドには常にやるべき作業があることがわかりました。接続上でハングアップしているため、他のゲストにサービスを提供することはできません。そうですか、そうであれば既製品の稼働率は大幅に向上しましたか?
要約すると、select を使用した後、まずスレッドの数を指定します。1人1スレッドで十分であり、selectと連携して複数チャネルの読み書きイベントを順番に処理することができ、1つのスレッドで複数チャネルを処理することができ、使用率が向上します。では、SELECT1 バージョンは何に適しているのでしょうか? 特に接続数が多い製品に適しています。ただし、トラフィックは比較的少ないです。
トラフィックが少ないとは何ですか?これらの顧客がこれらの読み取りおよび書き込み操作を頻繁に送信することを意味しますか? たとえば、ゲスト。彼が大量のデータを送信した場合、彼は私のスレッド内でこの人とのみ対処する可能性があります。このゲストは、処理するために大量のデータを送信しました。この期間中、他の顧客は冷遇されます。データ トラフィックが比較的少ないシナリオ。セレクターは、実際には非常に中心的な役割を果たし、すべてのチャネルでこれらの読み取りおよび書き込みイベントを監視できます。読み取りまたは書き込みイベントが発生すると、スレッドを実行してこれらの処理を実行します。これは、以前のサーバー側設計の選択バージョンの一部の改善です。

おすすめ

転載: blog.csdn.net/sunrj_niu/article/details/129539355