マルチスレッドソケットサーバーを書いています。ServerSocketChannel
接続を受け入れるためにnioを使用します。socketChannel
次に、ライターを使用して (別のスレッドで) 読み取りと書き込みをbufferedreader
行います。問題は、コマンドをPrintWriter
ロックして待機することです。データを受信する flush()
までスレッドをブロックします。BufferedReader
2 に答える
これは、レシーバーの読み取りが遅いことを示しています。これがブロッキング I/O の仕組みです。ノンブロッキング I/O が必要な場合は、既に NIO を使用しているため、既にその方法の一部になっています。ブロッキングモードでNIOを使用する意味がまったくわかりませんが。
@EJP が言うように、それは基本的にブロッキング IO の仕組みです。実際、この問題は、プロデューサーとコンシューマーが存在するアーキテクチャには固有のものです。プロデューサが消費者が消費できるよりも速く何か (この場合はテキスト出力の行) を生成する場合、プロデューサは最終的にブロックする必要があります。
どうすればこれを解決できますか? 最初に一般的なものをいくつか。
生産者が消費者が長期的にそれを消費するよりも速く生産する場合、あなたは岩と困難な場所の間にいます. プロデューサの生産速度を下げるか、コンシューマの消費速度を速めるか、パイプラインのオーバーヘッドを削減して同じ効果を得る必要があります。他に何も機能しません。
レートの不一致が一時的なものに過ぎない場合は、パイプラインに追加のバッファリングを追加することで、「問題を解決する」ことができます。間の接続にバッファリング機能がある場合は、それを増やすことができる場合があります。または、プロデューサーまたはコンシューマー側で追加のバッファリングを追加することもできます。
あなたの特定のケースで役立つかもしれないいくつかのことを次に示します。
プロデューサー スレッドに書き込む量を減らします。
コンシューマー スレッドでの作業を減らすか、それらをプロファイリングまたは調整して作業を高速化します。
同じ JVM 内の 2 つのスレッド間の通信にソケットを使用しないでください。調整できる場合は、Java PipeInputStream / PipeOutputStream ペアを使用するか、独自の同等のものをロールします。(ソケットを使用する場合、読み取りと書き込みには、システム コール、カーネル バッファーへのデータのコピー、カーネル バッファーからのデータのコピーなどが含まれます。)
通信をJVM の外に出す必要がある場合は
Buffered*
、基礎となるストリームにラッパーを使用して、読み取り/書き込み中に行われる syscall の数を減らすようにしてください。